forked from OSchip/llvm-project
When building types from declarators, instead of building two types (one for
the DeclaratorInfo, one for semantic analysis), just build a single type whose canonical type will reflect the semantic analysis (assuming the type is well-formed, of course). To make that work, make a few changes to the type system: * allow the nominal pointee type of a reference type to be a (possibly sugared) reference type. Also, preserve the original spelling of the reference type. Both of these can be ignored on canonical reference types. * Remove ObjCProtocolListType and preserve the associated source information on the various ObjC TypeLocs. Preserve the spelling of protocol lists except in the canonical form. * Preserve some level of source type structure on parameter types, but canonicalize on the canonical function type. This is still a WIP. Drops code size, makes strides towards accurate source location representation, slight (~1.7%) progression on Cocoa.h because of complexity drop. llvm-svn: 84907
This commit is contained in:
parent
2a3ffa9658
commit
fc93cf9777
|
@ -87,7 +87,6 @@ class ASTContext {
|
|||
llvm::FoldingSet<TypenameType> TypenameTypes;
|
||||
llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
|
||||
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
|
||||
llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes;
|
||||
llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
|
||||
|
||||
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
|
@ -437,7 +436,7 @@ public:
|
|||
|
||||
/// getLValueReferenceType - Return the uniqued reference to the type for an
|
||||
/// lvalue reference to the specified type.
|
||||
QualType getLValueReferenceType(QualType T);
|
||||
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true);
|
||||
|
||||
/// getRValueReferenceType - Return the uniqued reference to the type for an
|
||||
/// rvalue reference to the specified type.
|
||||
|
@ -547,10 +546,6 @@ public:
|
|||
ObjCProtocolDecl **ProtocolList = 0,
|
||||
unsigned NumProtocols = 0);
|
||||
|
||||
QualType getObjCProtocolListType(QualType T,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols);
|
||||
|
||||
/// getTypeOfType - GCC extension.
|
||||
QualType getTypeOfExprType(Expr *e);
|
||||
QualType getTypeOfType(QualType t);
|
||||
|
@ -847,6 +842,12 @@ public:
|
|||
return T->getCanonicalTypeInternal().getTypePtr();
|
||||
}
|
||||
|
||||
/// getCanonicalParamType - Return the canonical parameter type
|
||||
/// corresponding to the specific potentially non-canonical one.
|
||||
/// Qualifiers are stripped off, functions are turned into function
|
||||
/// pointers, and arrays decay one level into pointers.
|
||||
CanQualType getCanonicalParamType(QualType T);
|
||||
|
||||
/// \brief Determine whether the given types are equivalent.
|
||||
bool hasSameType(QualType T1, QualType T2) {
|
||||
return getCanonicalType(T1) == getCanonicalType(T2);
|
||||
|
|
|
@ -444,6 +444,7 @@ public:
|
|||
}
|
||||
|
||||
bool isCanonical() const;
|
||||
bool isCanonicalAsParam() const;
|
||||
|
||||
/// isNull - Return true if this QualType doesn't point to a type yet.
|
||||
bool isNull() const {
|
||||
|
@ -1093,19 +1094,50 @@ public:
|
|||
class ReferenceType : public Type, public llvm::FoldingSetNode {
|
||||
QualType PointeeType;
|
||||
|
||||
/// True if the type was originally spelled with an lvalue sigil.
|
||||
/// This is never true of rvalue references but can also be false
|
||||
/// on lvalue references because of C++0x [dcl.typedef]p9,
|
||||
/// as follows:
|
||||
///
|
||||
/// typedef int &ref; // lvalue, spelled lvalue
|
||||
/// typedef int &&rvref; // rvalue
|
||||
/// ref &a; // lvalue, inner ref, spelled lvalue
|
||||
/// ref &&a; // lvalue, inner ref
|
||||
/// rvref &a; // lvalue, inner ref, spelled lvalue
|
||||
/// rvref &&a; // rvalue, inner ref
|
||||
bool SpelledAsLValue;
|
||||
|
||||
/// True if the inner type is a reference type. This only happens
|
||||
/// in non-canonical forms.
|
||||
bool InnerRef;
|
||||
|
||||
protected:
|
||||
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) :
|
||||
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
|
||||
bool SpelledAsLValue) :
|
||||
Type(tc, CanonicalRef, Referencee->isDependentType()),
|
||||
PointeeType(Referencee) {
|
||||
PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue),
|
||||
InnerRef(Referencee->isReferenceType()) {
|
||||
}
|
||||
public:
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
bool isSpelledAsLValue() const { return SpelledAsLValue; }
|
||||
|
||||
QualType getPointeeTypeAsWritten() const { return PointeeType; }
|
||||
QualType getPointeeType() const {
|
||||
// FIXME: this might strip inner qualifiers; okay?
|
||||
const ReferenceType *T = this;
|
||||
while (T->InnerRef)
|
||||
T = T->PointeeType->getAs<ReferenceType>();
|
||||
return T->PointeeType;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getPointeeType());
|
||||
Profile(ID, PointeeType, SpelledAsLValue);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) {
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
QualType Referencee,
|
||||
bool SpelledAsLValue) {
|
||||
ID.AddPointer(Referencee.getAsOpaquePtr());
|
||||
ID.AddBoolean(SpelledAsLValue);
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
|
@ -1118,9 +1150,10 @@ public:
|
|||
/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
|
||||
///
|
||||
class LValueReferenceType : public ReferenceType {
|
||||
LValueReferenceType(QualType Referencee, QualType CanonicalRef) :
|
||||
ReferenceType(LValueReference, Referencee, CanonicalRef) {
|
||||
}
|
||||
LValueReferenceType(QualType Referencee, QualType CanonicalRef,
|
||||
bool SpelledAsLValue) :
|
||||
ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue)
|
||||
{}
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
|
@ -1139,7 +1172,7 @@ public:
|
|||
///
|
||||
class RValueReferenceType : public ReferenceType {
|
||||
RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
|
||||
ReferenceType(RValueReference, Referencee, CanonicalRef) {
|
||||
ReferenceType(RValueReference, Referencee, CanonicalRef, false) {
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
public:
|
||||
|
@ -2433,9 +2466,9 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
|
|||
// List is sorted on protocol name. No protocol is enterred more than once.
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
|
||||
|
||||
ObjCInterfaceType(ObjCInterfaceDecl *D,
|
||||
ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D,
|
||||
ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCInterface, QualType(), /*Dependent=*/false),
|
||||
Type(ObjCInterface, Canonical, /*Dependent=*/false),
|
||||
Decl(D), Protocols(Protos, Protos+NumP) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
@ -2481,8 +2514,9 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
|
|||
// List is sorted on protocol name. No protocol is entered more than once.
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
|
||||
|
||||
ObjCObjectPointerType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
|
||||
ObjCObjectPointerType(QualType Canonical, QualType T,
|
||||
ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
|
||||
PointeeType(T), Protocols(Protos, Protos+NumP) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
|
@ -2547,49 +2581,6 @@ public:
|
|||
static bool classof(const ObjCObjectPointerType *) { return true; }
|
||||
};
|
||||
|
||||
/// \brief An ObjC Protocol list that qualifies a type.
|
||||
///
|
||||
/// This is used only for keeping detailed type source information, it should
|
||||
/// not participate in the semantics of the type system.
|
||||
/// The protocol list is not canonicalized.
|
||||
class ObjCProtocolListType : public Type, public llvm::FoldingSetNode {
|
||||
QualType BaseType;
|
||||
|
||||
// List of protocols for this protocol conforming object type.
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
|
||||
|
||||
ObjCProtocolListType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) :
|
||||
Type(ObjCProtocolList, QualType(), /*Dependent=*/false),
|
||||
BaseType(T), Protocols(Protos, Protos+NumP) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
public:
|
||||
QualType getBaseType() const { return BaseType; }
|
||||
|
||||
/// \brief Provides access to the list of protocols qualifying the base type.
|
||||
typedef llvm::SmallVector<ObjCProtocolDecl*, 4>::const_iterator qual_iterator;
|
||||
|
||||
qual_iterator qual_begin() const { return Protocols.begin(); }
|
||||
qual_iterator qual_end() const { return Protocols.end(); }
|
||||
bool qual_empty() const { return Protocols.size() == 0; }
|
||||
|
||||
/// \brief Return the number of qualifying protocols.
|
||||
unsigned getNumProtocols() const { return Protocols.size(); }
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
|
||||
ObjCProtocolDecl **protocols, unsigned NumProtocols);
|
||||
virtual void getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const;
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCProtocolList;
|
||||
}
|
||||
static bool classof(const ObjCProtocolListType *) { return true; }
|
||||
};
|
||||
|
||||
/// A qualifier set is used to build a set of qualifiers.
|
||||
class QualifierCollector : public Qualifiers {
|
||||
ASTContext *Context;
|
||||
|
@ -2633,6 +2624,13 @@ inline bool QualType::isCanonical() const {
|
|||
return T->isCanonicalUnqualified();
|
||||
}
|
||||
|
||||
inline bool QualType::isCanonicalAsParam() const {
|
||||
if (hasQualifiers()) return false;
|
||||
const Type *T = getTypePtr();
|
||||
return T->isCanonicalUnqualified() &&
|
||||
!isa<FunctionType>(T) && !isa<ArrayType>(T);
|
||||
}
|
||||
|
||||
inline void QualType::removeConst() {
|
||||
removeFastQualifiers(Qualifiers::Const);
|
||||
}
|
||||
|
|
|
@ -375,48 +375,52 @@ class SubstTemplateTypeParmTypeLoc :
|
|||
SubstTemplateTypeParmType> {
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for ObjC interfaces.
|
||||
class ObjCInterfaceTypeLoc : public TypeSpecTypeLoc<ObjCInterfaceTypeLoc,
|
||||
ObjCInterfaceType> {
|
||||
public:
|
||||
ObjCInterfaceDecl *getIFaceDecl() const {
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ObjCProtocolListLocInfo {
|
||||
SourceLocation LAngleLoc, RAngleLoc;
|
||||
SourceLocation LAngleLoc;
|
||||
SourceLocation RAngleLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for ObjC protocol lists.
|
||||
class ObjCProtocolListTypeLoc
|
||||
: public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
ObjCProtocolListTypeLoc,
|
||||
ObjCProtocolListType,
|
||||
ObjCProtocolListLocInfo> {
|
||||
// A helper class for defining ObjC TypeLocs that can qualified with
|
||||
// protocols.
|
||||
//
|
||||
// TypeClass basically has to be either ObjCInterfaceType or
|
||||
// ObjCObjectPointerType.
|
||||
template <class Derived, class TypeClass, class LocalData>
|
||||
class ObjCProtocolListTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
Derived,
|
||||
TypeClass,
|
||||
LocalData> {
|
||||
// SourceLocations are stored after Info, one for each Protocol.
|
||||
SourceLocation *getProtocolLocArray() const {
|
||||
return (SourceLocation*) getExtraLocalData();
|
||||
return (SourceLocation*) this->getExtraLocalData();
|
||||
}
|
||||
|
||||
protected:
|
||||
void initializeLocalBase(SourceLocation Loc) {
|
||||
setLAngleLoc(Loc);
|
||||
setRAngleLoc(Loc);
|
||||
for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
|
||||
setProtocolLoc(i, Loc);
|
||||
}
|
||||
|
||||
public:
|
||||
SourceLocation getLAngleLoc() const {
|
||||
return getLocalData()->LAngleLoc;
|
||||
return this->getLocalData()->LAngleLoc;
|
||||
}
|
||||
void setLAngleLoc(SourceLocation Loc) {
|
||||
getLocalData()->LAngleLoc = Loc;
|
||||
this->getLocalData()->LAngleLoc = Loc;
|
||||
}
|
||||
|
||||
SourceLocation getRAngleLoc() const {
|
||||
return getLocalData()->RAngleLoc;
|
||||
return this->getLocalData()->RAngleLoc;
|
||||
}
|
||||
void setRAngleLoc(SourceLocation Loc) {
|
||||
getLocalData()->RAngleLoc = Loc;
|
||||
this->getLocalData()->RAngleLoc = Loc;
|
||||
}
|
||||
|
||||
unsigned getNumProtocols() const {
|
||||
return getTypePtr()->getNumProtocols();
|
||||
return this->getTypePtr()->getNumProtocols();
|
||||
}
|
||||
|
||||
SourceLocation getProtocolLoc(unsigned i) const {
|
||||
|
@ -430,34 +434,123 @@ public:
|
|||
|
||||
ObjCProtocolDecl *getProtocol(unsigned i) const {
|
||||
assert(i < getNumProtocols() && "Index is out of bounds!");
|
||||
return *(getTypePtr()->qual_begin() + i);
|
||||
return *(this->getTypePtr()->qual_begin() + i);
|
||||
}
|
||||
|
||||
TypeLoc getBaseTypeLoc() const {
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(getLAngleLoc(), getRAngleLoc());
|
||||
}
|
||||
|
||||
void initializeLocal(SourceLocation Loc) {
|
||||
setLAngleLoc(Loc);
|
||||
setRAngleLoc(Loc);
|
||||
for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
|
||||
setProtocolLoc(i, Loc);
|
||||
initializeLocalBase(Loc);
|
||||
}
|
||||
|
||||
/// \brief Returns the size of the type source info data block that is
|
||||
/// specific to this type.
|
||||
unsigned getExtraLocalDataSize() const {
|
||||
return getNumProtocols() * sizeof(SourceLocation);
|
||||
return this->getNumProtocols() * sizeof(SourceLocation);
|
||||
}
|
||||
|
||||
QualType getInnerType() const { return getTypePtr()->getBaseType(); }
|
||||
};
|
||||
|
||||
|
||||
struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
/// \brief Wrapper for source info for ObjC interfaces.
|
||||
class ObjCInterfaceTypeLoc :
|
||||
public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc,
|
||||
ObjCInterfaceType,
|
||||
ObjCInterfaceLocInfo> {
|
||||
public:
|
||||
ObjCInterfaceDecl *getIFaceDecl() const {
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
|
||||
SourceLocation getNameLoc() const {
|
||||
return getLocalData()->NameLoc;
|
||||
}
|
||||
|
||||
void setNameLoc(SourceLocation Loc) {
|
||||
getLocalData()->NameLoc = Loc;
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const {
|
||||
if (getNumProtocols())
|
||||
return SourceRange(getNameLoc(), getRAngleLoc());
|
||||
else
|
||||
return SourceRange(getNameLoc(), getNameLoc());
|
||||
}
|
||||
|
||||
void initializeLocal(SourceLocation Loc) {
|
||||
initializeLocalBase(Loc);
|
||||
setNameLoc(Loc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo {
|
||||
SourceLocation StarLoc;
|
||||
bool HasProtocols;
|
||||
bool HasBaseType;
|
||||
};
|
||||
|
||||
/// Wraps an ObjCPointerType with source location information. Note
|
||||
/// that not all ObjCPointerTypes actually have a star location; nor
|
||||
/// are protocol locations necessarily written in the source just
|
||||
/// because they're present on the type.
|
||||
class ObjCObjectPointerTypeLoc :
|
||||
public ObjCProtocolListTypeLoc<ObjCObjectPointerTypeLoc,
|
||||
ObjCObjectPointerType,
|
||||
ObjCObjectPointerLocInfo> {
|
||||
public:
|
||||
bool hasProtocolsAsWritten() const {
|
||||
return getLocalData()->HasProtocols;
|
||||
}
|
||||
|
||||
void setHasProtocolsAsWritten(bool HasProtocols) {
|
||||
getLocalData()->HasProtocols = HasProtocols;
|
||||
}
|
||||
|
||||
bool hasBaseTypeAsWritten() const {
|
||||
return getLocalData()->HasBaseType;
|
||||
}
|
||||
|
||||
void setHasBaseTypeAsWritten(bool HasBaseType) {
|
||||
getLocalData()->HasBaseType = HasBaseType;
|
||||
}
|
||||
|
||||
SourceLocation getStarLoc() const {
|
||||
return getLocalData()->StarLoc;
|
||||
}
|
||||
|
||||
void setStarLoc(SourceLocation Loc) {
|
||||
getLocalData()->StarLoc = Loc;
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const {
|
||||
// Being written with protocols is incompatible with being written
|
||||
// with a star.
|
||||
if (hasProtocolsAsWritten())
|
||||
return SourceRange(getLAngleLoc(), getRAngleLoc());
|
||||
else
|
||||
return SourceRange(getStarLoc(), getStarLoc());
|
||||
}
|
||||
|
||||
void initializeLocal(SourceLocation Loc) {
|
||||
initializeLocalBase(Loc);
|
||||
setHasProtocolsAsWritten(false);
|
||||
setHasBaseTypeAsWritten(false);
|
||||
setStarLoc(Loc);
|
||||
}
|
||||
|
||||
TypeLoc getBaseTypeLoc() const {
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
QualType getInnerType() const {
|
||||
return getTypePtr()->getPointeeType();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct PointerLikeLocInfo {
|
||||
SourceLocation StarLoc;
|
||||
|
@ -534,6 +627,10 @@ public:
|
|||
|
||||
class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
|
||||
ReferenceType> {
|
||||
public:
|
||||
QualType getInnerType() const {
|
||||
return getTypePtr()->getPointeeTypeAsWritten();
|
||||
}
|
||||
};
|
||||
|
||||
class LValueReferenceTypeLoc :
|
||||
|
@ -562,20 +659,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// Wraps an ObjCPointerType with source location information. Note
|
||||
/// that not all ObjCPointerTypes actually have a star location.
|
||||
class ObjCObjectPointerTypeLoc :
|
||||
public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc,
|
||||
ObjCObjectPointerType> {
|
||||
public:
|
||||
SourceLocation getStarLoc() const {
|
||||
return getSigilLoc();
|
||||
}
|
||||
void setStarLoc(SourceLocation Loc) {
|
||||
setSigilLoc(Loc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct FunctionLocInfo {
|
||||
SourceLocation LParenLoc, RParenLoc;
|
||||
|
|
|
@ -86,7 +86,6 @@ NON_CANONICAL_TYPE(QualifiedName, Type)
|
|||
DEPENDENT_TYPE(Typename, Type)
|
||||
TYPE(ObjCInterface, Type)
|
||||
TYPE(ObjCObjectPointer, Type)
|
||||
NON_CANONICAL_TYPE(ObjCProtocolList, Type)
|
||||
|
||||
// These types are always leaves in the type hierarchy.
|
||||
#ifdef LEAF_TYPE
|
||||
|
@ -94,7 +93,6 @@ LEAF_TYPE(Enum)
|
|||
LEAF_TYPE(Builtin)
|
||||
LEAF_TYPE(FixedWidthInt)
|
||||
LEAF_TYPE(ObjCInterface)
|
||||
LEAF_TYPE(ObjCObjectPointer)
|
||||
LEAF_TYPE(TemplateTypeParm)
|
||||
#undef LEAF_TYPE
|
||||
#endif
|
||||
|
|
|
@ -397,14 +397,12 @@ namespace clang {
|
|||
TYPE_OBJC_INTERFACE = 21,
|
||||
/// \brief An ObjCObjectPointerType record.
|
||||
TYPE_OBJC_OBJECT_POINTER = 22,
|
||||
/// \brief An ObjCProtocolListType record.
|
||||
TYPE_OBJC_PROTOCOL_LIST = 23,
|
||||
/// \brief a DecltypeType record.
|
||||
TYPE_DECLTYPE = 24,
|
||||
TYPE_DECLTYPE = 23,
|
||||
/// \brief An ElaboratedType record.
|
||||
TYPE_ELABORATED = 25,
|
||||
TYPE_ELABORATED = 24,
|
||||
/// \brief A SubstTemplateTypeParmType record.
|
||||
TYPE_SUBST_TEMPLATE_TYPE_PARM = 26
|
||||
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
|
|
|
@ -555,10 +555,6 @@ ASTContext::getTypeInfo(const Type *T) {
|
|||
assert(false && "Should not see dependent types");
|
||||
break;
|
||||
|
||||
case Type::ObjCProtocolList:
|
||||
assert(false && "Should not see protocol list types");
|
||||
break;
|
||||
|
||||
case Type::FunctionNoProto:
|
||||
case Type::FunctionProto:
|
||||
// GCC extension: alignof(function) = 32 bits
|
||||
|
@ -1235,22 +1231,25 @@ QualType ASTContext::getBlockPointerType(QualType T) {
|
|||
|
||||
/// getLValueReferenceType - Return the uniqued reference to the type for an
|
||||
/// lvalue reference to the specified type.
|
||||
QualType ASTContext::getLValueReferenceType(QualType T) {
|
||||
QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) {
|
||||
// Unique pointers, to guarantee there is only one pointer of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ReferenceType::Profile(ID, T);
|
||||
ReferenceType::Profile(ID, T, SpelledAsLValue);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (LValueReferenceType *RT =
|
||||
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(RT, 0);
|
||||
|
||||
const ReferenceType *InnerRef = T->getAs<ReferenceType>();
|
||||
|
||||
// If the referencee type isn't canonical, this won't be a canonical type
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getLValueReferenceType(getCanonicalType(T));
|
||||
if (!SpelledAsLValue || InnerRef || !T.isCanonical()) {
|
||||
QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
|
||||
Canonical = getLValueReferenceType(getCanonicalType(PointeeType));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
LValueReferenceType *NewIP =
|
||||
|
@ -1259,9 +1258,11 @@ QualType ASTContext::getLValueReferenceType(QualType T) {
|
|||
}
|
||||
|
||||
LValueReferenceType *New
|
||||
= new (*this, TypeAlignment) LValueReferenceType(T, Canonical);
|
||||
= new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
|
||||
SpelledAsLValue);
|
||||
Types.push_back(New);
|
||||
LValueReferenceTypes.InsertNode(New, InsertPos);
|
||||
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
|
@ -1271,18 +1272,21 @@ QualType ASTContext::getRValueReferenceType(QualType T) {
|
|||
// Unique pointers, to guarantee there is only one pointer of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ReferenceType::Profile(ID, T);
|
||||
ReferenceType::Profile(ID, T, false);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (RValueReferenceType *RT =
|
||||
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(RT, 0);
|
||||
|
||||
const ReferenceType *InnerRef = T->getAs<ReferenceType>();
|
||||
|
||||
// If the referencee type isn't canonical, this won't be a canonical type
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getRValueReferenceType(getCanonicalType(T));
|
||||
if (InnerRef || !T.isCanonical()) {
|
||||
QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
|
||||
Canonical = getRValueReferenceType(getCanonicalType(PointeeType));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
RValueReferenceType *NewIP =
|
||||
|
@ -1603,12 +1607,6 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
|||
unsigned TypeQuals, bool hasExceptionSpec,
|
||||
bool hasAnyExceptionSpec, unsigned NumExs,
|
||||
const QualType *ExArray, bool NoReturn) {
|
||||
if (LangOpts.CPlusPlus) {
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
assert(!ArgArray[i].hasQualifiers() &&
|
||||
"C++ arguments can't have toplevel qualifiers!");
|
||||
}
|
||||
|
||||
// Unique functions, to guarantee there is only one function of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
|
@ -1622,11 +1620,9 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
|||
return QualType(FTP, 0);
|
||||
|
||||
// Determine whether the type being created is already canonical or not.
|
||||
bool isCanonical = ResultTy.isCanonical();
|
||||
if (hasExceptionSpec)
|
||||
isCanonical = false;
|
||||
bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical();
|
||||
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
|
||||
if (!ArgArray[i].isCanonical())
|
||||
if (!ArgArray[i].isCanonicalAsParam())
|
||||
isCanonical = false;
|
||||
|
||||
// If this type isn't canonical, get the canonical version of it.
|
||||
|
@ -1636,7 +1632,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
|||
llvm::SmallVector<QualType, 16> CanonicalArgs;
|
||||
CanonicalArgs.reserve(NumArgs);
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
CanonicalArgs.push_back(getCanonicalType(ArgArray[i]));
|
||||
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
|
||||
|
||||
Canonical = getFunctionType(getCanonicalType(ResultTy),
|
||||
CanonicalArgs.data(), NumArgs,
|
||||
|
@ -1920,7 +1916,17 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
|
|||
return LHS->getDeclName() < RHS->getDeclName();
|
||||
}
|
||||
|
||||
static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
|
||||
static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
if (NumProtocols == 0) return true;
|
||||
|
||||
for (unsigned i = 1; i != NumProtocols; ++i)
|
||||
if (!CmpProtocolNames(Protocols[i-1], Protocols[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
|
||||
unsigned &NumProtocols) {
|
||||
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
|
||||
|
||||
|
@ -1937,10 +1943,6 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
|
|||
QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
if (NumProtocols)
|
||||
SortAndUniqueProtocols(Protocols, NumProtocols);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols);
|
||||
|
||||
|
@ -1949,9 +1951,31 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
|
|||
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
QualType Canonical;
|
||||
if (!InterfaceT.isCanonical() ||
|
||||
!areSortedAndUniqued(Protocols, NumProtocols)) {
|
||||
if (!areSortedAndUniqued(Protocols, NumProtocols)) {
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols);
|
||||
unsigned UniqueCount = NumProtocols;
|
||||
|
||||
std::copy(Protocols, Protocols + NumProtocols, Sorted.begin());
|
||||
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
|
||||
|
||||
Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
|
||||
&Sorted[0], UniqueCount);
|
||||
} else {
|
||||
Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
|
||||
Protocols, NumProtocols);
|
||||
}
|
||||
|
||||
// Regenerate InsertPos.
|
||||
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
// No Match;
|
||||
ObjCObjectPointerType *QType = new (*this, TypeAlignment)
|
||||
ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols);
|
||||
ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols);
|
||||
|
||||
Types.push_back(QType);
|
||||
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
|
||||
|
@ -1962,10 +1986,6 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
|
|||
/// specified ObjC interface decl. The list of protocols is optional.
|
||||
QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
||||
ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
|
||||
if (NumProtocols)
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
SortAndUniqueProtocols(Protocols, NumProtocols);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols);
|
||||
|
||||
|
@ -1974,34 +1994,29 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
|||
ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// No Match;
|
||||
// Sort the protocol list alphabetically to canonicalize it.
|
||||
QualType Canonical;
|
||||
if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) {
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols);
|
||||
std::copy(Protocols, Protocols + NumProtocols, Sorted.begin());
|
||||
|
||||
unsigned UniqueCount = NumProtocols;
|
||||
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
|
||||
|
||||
Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount);
|
||||
|
||||
ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
ObjCInterfaceType *QType = new (*this, TypeAlignment)
|
||||
ObjCInterfaceType(const_cast<ObjCInterfaceDecl*>(Decl),
|
||||
ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
|
||||
Protocols, NumProtocols);
|
||||
|
||||
Types.push_back(QType);
|
||||
ObjCInterfaceTypes.InsertNode(QType, InsertPos);
|
||||
return QualType(QType, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getObjCProtocolListType(QualType T,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (ObjCProtocolListType *QT =
|
||||
ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(QT, 0);
|
||||
|
||||
// No Match;
|
||||
ObjCProtocolListType *QType = new (*this, TypeAlignment)
|
||||
ObjCProtocolListType(T, Protocols, NumProtocols);
|
||||
Types.push_back(QType);
|
||||
ObjCProtocolListTypes.InsertNode(QType, InsertPos);
|
||||
return QualType(QType, 0);
|
||||
}
|
||||
|
||||
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
|
||||
/// TypeOfExprType AST's (since expression's are never shared). For example,
|
||||
/// multiple declarations that refer to "typeof(x)" all contain different
|
||||
|
@ -2155,6 +2170,24 @@ QualType ASTContext::getPointerDiffType() const {
|
|||
// Type Operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CanQualType ASTContext::getCanonicalParamType(QualType T) {
|
||||
// Push qualifiers into arrays, and then discard any remaining
|
||||
// qualifiers.
|
||||
T = getCanonicalType(T);
|
||||
const Type *Ty = T.getTypePtr();
|
||||
|
||||
QualType Result;
|
||||
if (isa<ArrayType>(Ty)) {
|
||||
Result = getArrayDecayedType(QualType(Ty,0));
|
||||
} else if (isa<FunctionType>(Ty)) {
|
||||
Result = getPointerType(QualType(Ty, 0));
|
||||
} else {
|
||||
Result = QualType(Ty, 0);
|
||||
}
|
||||
|
||||
return CanQualType::CreateUnsafe(Result);
|
||||
}
|
||||
|
||||
/// getCanonicalType - Return the canonical (structural) type corresponding to
|
||||
/// the specified potentially non-canonical type. The non-canonical version
|
||||
/// of a type may have many "decorated" versions of types. Decorators can
|
||||
|
|
|
@ -724,18 +724,6 @@ void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
|
|||
Profile(ID, getPointeeType(), 0, 0);
|
||||
}
|
||||
|
||||
void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
QualType OIT, ObjCProtocolDecl **protocols,
|
||||
unsigned NumProtocols) {
|
||||
ID.AddPointer(OIT.getAsOpaquePtr());
|
||||
for (unsigned i = 0; i != NumProtocols; i++)
|
||||
ID.AddPointer(protocols[i]);
|
||||
}
|
||||
|
||||
void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getBaseType(), &Protocols[0], getNumProtocols());
|
||||
}
|
||||
|
||||
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
|
||||
/// potentially looking through *all* consequtive typedefs. This returns the
|
||||
/// sum of the type qualifiers, so if you have:
|
||||
|
@ -1059,10 +1047,10 @@ void LValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli
|
|||
|
||||
// Handle things like 'int (&A)[4];' correctly.
|
||||
// FIXME: this should include vectors, but vectors use attributes I guess.
|
||||
if (isa<ArrayType>(getPointeeType()))
|
||||
if (isa<ArrayType>(getPointeeTypeAsWritten()))
|
||||
S = '(' + S + ')';
|
||||
|
||||
getPointeeType().getAsStringInternal(S, Policy);
|
||||
getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
|
@ -1070,10 +1058,10 @@ void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli
|
|||
|
||||
// Handle things like 'int (&&A)[4];' correctly.
|
||||
// FIXME: this should include vectors, but vectors use attributes I guess.
|
||||
if (isa<ArrayType>(getPointeeType()))
|
||||
if (isa<ArrayType>(getPointeeTypeAsWritten()))
|
||||
S = '(' + S + ')';
|
||||
|
||||
getPointeeType().getAsStringInternal(S, Policy);
|
||||
getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
|
||||
}
|
||||
|
||||
void MemberPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
|
||||
|
@ -1463,25 +1451,6 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
|
|||
InnerString = ObjCQIString + InnerString;
|
||||
}
|
||||
|
||||
void ObjCProtocolListType::getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const {
|
||||
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||
InnerString = ' ' + InnerString;
|
||||
|
||||
std::string ObjCQIString = getBaseType().getAsString(Policy);
|
||||
ObjCQIString += '<';
|
||||
bool isFirst = true;
|
||||
for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
|
||||
if (isFirst)
|
||||
isFirst = false;
|
||||
else
|
||||
ObjCQIString += ',';
|
||||
ObjCQIString += (*I)->getNameAsString();
|
||||
}
|
||||
ObjCQIString += '>';
|
||||
InnerString = ObjCQIString + InnerString;
|
||||
}
|
||||
|
||||
void ElaboratedType::getAsStringInternal(std::string &InnerString,
|
||||
const PrintingPolicy &Policy) const {
|
||||
std::string TypeStr;
|
||||
|
|
|
@ -248,7 +248,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
|
|||
FD = PrimaryTemplate->getTemplatedDecl();
|
||||
}
|
||||
|
||||
mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), MangleReturnType);
|
||||
// Do the canonicalization out here because parameter types can
|
||||
// undergo additional canonicalization (e.g. array decay).
|
||||
FunctionType *FT = cast<FunctionType>(Context.getASTContext()
|
||||
.getCanonicalType(FD->getType()));
|
||||
|
||||
mangleBareFunctionType(FT, MangleReturnType);
|
||||
}
|
||||
|
||||
static bool isStdNamespace(const DeclContext *DC) {
|
||||
|
|
|
@ -1964,16 +1964,6 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
|||
return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
|
||||
}
|
||||
|
||||
case pch::TYPE_OBJC_PROTOCOL_LIST: {
|
||||
unsigned Idx = 0;
|
||||
QualType OIT = GetType(Record[Idx++]);
|
||||
unsigned NumProtos = Record[Idx++];
|
||||
llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
|
||||
for (unsigned I = 0; I != NumProtos; ++I)
|
||||
Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
|
||||
return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos);
|
||||
}
|
||||
|
||||
case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
|
||||
unsigned Idx = 0;
|
||||
QualType Parm = GetType(Record[Idx++]);
|
||||
|
@ -2124,16 +2114,21 @@ void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
|
|||
}
|
||||
void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) {
|
||||
TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
TL.setHasBaseTypeAsWritten(Record[Idx++]);
|
||||
TL.setHasProtocolsAsWritten(Record[Idx++]);
|
||||
if (TL.hasProtocolsAsWritten())
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
}
|
||||
|
||||
DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
|
||||
unsigned &Idx) {
|
||||
|
|
|
@ -248,15 +248,6 @@ PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
|
|||
Code = pch::TYPE_OBJC_OBJECT_POINTER;
|
||||
}
|
||||
|
||||
void PCHTypeWriter::VisitObjCProtocolListType(const ObjCProtocolListType *T) {
|
||||
Writer.AddTypeRef(T->getBaseType(), Record);
|
||||
Record.push_back(T->getNumProtocols());
|
||||
for (ObjCProtocolListType::qual_iterator I = T->qual_begin(),
|
||||
E = T->qual_end(); I != E; ++I)
|
||||
Writer.AddDeclRef(*I, Record);
|
||||
Code = pch::TYPE_OBJC_PROTOCOL_LIST;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
|
@ -387,16 +378,21 @@ void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
|
|||
}
|
||||
void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getStarLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getStarLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
|
||||
Record.push_back(TL.hasBaseTypeAsWritten());
|
||||
Record.push_back(TL.hasProtocolsAsWritten());
|
||||
if (TL.hasProtocolsAsWritten())
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PCHWriter Implementation
|
||||
|
@ -569,7 +565,6 @@ void PCHWriter::WriteBlockInfoBlock() {
|
|||
RECORD(TYPE_ENUM);
|
||||
RECORD(TYPE_OBJC_INTERFACE);
|
||||
RECORD(TYPE_OBJC_OBJECT_POINTER);
|
||||
RECORD(TYPE_OBJC_PROTOCOL_LIST);
|
||||
RECORD(DECL_ATTR);
|
||||
RECORD(DECL_TRANSLATION_UNIT);
|
||||
RECORD(DECL_TYPEDEF);
|
||||
|
|
|
@ -120,11 +120,12 @@ public:
|
|||
TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
|
||||
: LocResolverBase(ctx, loc), ParentDecl(pd) { }
|
||||
|
||||
ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
|
||||
ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
|
||||
ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
|
||||
ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
|
||||
ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
|
||||
ASTLocation VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL);
|
||||
ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
|
||||
ASTLocation VisitTypeLoc(TypeLoc TL);
|
||||
};
|
||||
|
||||
|
@ -349,6 +350,24 @@ ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
|
|||
return ASTLocation(D);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
|
||||
// Continue the 'id' magic by making the builtin type (which cannot
|
||||
// actually be spelled) map to the typedef.
|
||||
BuiltinType *T = TL.getTypePtr();
|
||||
if (T->getKind() == BuiltinType::ObjCId) {
|
||||
TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
|
||||
return ASTLocation(ParentDecl, D, TL.getNameLoc());
|
||||
}
|
||||
|
||||
// Same thing with 'Class'.
|
||||
if (T->getKind() == BuiltinType::ObjCClass) {
|
||||
TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
|
||||
return ASTLocation(ParentDecl, D, TL.getNameLoc());
|
||||
}
|
||||
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
@ -389,12 +408,6 @@ ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL)
|
|||
"Should visit only after verifying that loc is in range");
|
||||
if (ContainsLocation(TL.getNameLoc()))
|
||||
return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
||||
for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
|
||||
SourceLocation L = TL.getProtocolLoc(i);
|
||||
|
@ -408,6 +421,24 @@ ASTLocation TypeLocResolver::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLo
|
|||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
||||
if (TL.hasProtocolsAsWritten()) {
|
||||
for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
|
||||
SourceLocation L = TL.getProtocolLoc(i);
|
||||
RangePos RP = CheckRange(L);
|
||||
if (RP == AfterLoc)
|
||||
break;
|
||||
if (RP == ContainsLoc)
|
||||
return ASTLocation(ParentDecl, TL.getProtocol(i), L);
|
||||
}
|
||||
}
|
||||
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
|
|
@ -448,7 +448,7 @@ public:
|
|||
//
|
||||
QualType adjustParameterType(QualType T);
|
||||
QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
|
||||
bool &IsInvalid, QualType &SourceTy);
|
||||
bool &IsInvalid);
|
||||
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
|
||||
QualType BuildPointerType(QualType T, unsigned Quals,
|
||||
SourceLocation Loc, DeclarationName Entity);
|
||||
|
@ -3755,22 +3755,6 @@ public:
|
|||
QualType FieldTy, const Expr *BitWidth,
|
||||
bool *ZeroWidth = 0);
|
||||
|
||||
/// adjustFunctionParamType - Converts the type of a function parameter to a
|
||||
// type that can be passed as an argument type to
|
||||
/// ASTContext::getFunctionType.
|
||||
///
|
||||
/// C++ [dcl.fct]p3: "...Any cv-qualifier modifying a parameter type is
|
||||
/// deleted. Such cv-qualifiers affect only the definition of the parameter
|
||||
/// within the body of the function; they do not affect the function type.
|
||||
QualType adjustFunctionParamType(QualType T) const {
|
||||
if (!Context.getLangOptions().CPlusPlus)
|
||||
return T;
|
||||
return
|
||||
T->isDependentType() ? T.getUnqualifiedType()
|
||||
: T.getDesugaredType().getUnqualifiedType();
|
||||
|
||||
}
|
||||
|
||||
/// \name Code completion
|
||||
//@{
|
||||
void setCodeCompleteConsumer(CodeCompleteConsumer *CCC);
|
||||
|
|
|
@ -4281,8 +4281,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
|
|||
// friend templates because ActOnTag never produces a ClassTemplateDecl
|
||||
// for a TUK_Friend.
|
||||
bool invalid = false;
|
||||
QualType SourceTy;
|
||||
QualType T = ConvertDeclSpecToType(DS, Loc, invalid, SourceTy);
|
||||
QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
|
||||
if (invalid) return DeclPtrTy();
|
||||
|
||||
// This is definitely an error in C++98. It's probably meant to
|
||||
|
|
|
@ -52,16 +52,14 @@ QualType Sema::adjustParameterType(QualType T) {
|
|||
/// object.
|
||||
/// \param DS the declaration specifiers
|
||||
/// \param DeclLoc The location of the declarator identifier or invalid if none.
|
||||
/// \param SourceTy QualType representing the type as written in source form.
|
||||
/// \returns The type described by the declaration specifiers. This function
|
||||
/// never returns null.
|
||||
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
|
||||
SourceLocation DeclLoc,
|
||||
bool &isInvalid, QualType &SourceTy) {
|
||||
bool &isInvalid) {
|
||||
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
|
||||
// checking.
|
||||
QualType Result;
|
||||
SourceTy = Result;
|
||||
|
||||
switch (DS.getTypeSpecType()) {
|
||||
case DeclSpec::TST_void:
|
||||
|
@ -106,9 +104,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
|
|||
case DeclSpec::TST_unspecified:
|
||||
// "<proto1,proto2>" is an objc qualified ID with a missing id.
|
||||
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
|
||||
SourceTy = Context.getObjCProtocolListType(QualType(),
|
||||
(ObjCProtocolDecl**)PQ,
|
||||
DS.getNumProtocolQualifiers());
|
||||
Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
|
||||
(ObjCProtocolDecl**)PQ,
|
||||
DS.getNumProtocolQualifiers());
|
||||
|
@ -226,9 +221,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
|
|||
Result = GetTypeFromParser(DS.getTypeRep());
|
||||
|
||||
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
|
||||
SourceTy = Context.getObjCProtocolListType(Result,
|
||||
(ObjCProtocolDecl**)PQ,
|
||||
DS.getNumProtocolQualifiers());
|
||||
if (const ObjCInterfaceType *
|
||||
Interface = Result->getAs<ObjCInterfaceType>()) {
|
||||
// It would be nice if protocol qualifiers were only stored with the
|
||||
|
@ -385,8 +377,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
|
|||
Result = Context.getQualifiedType(Result, Quals);
|
||||
}
|
||||
|
||||
if (SourceTy.isNull())
|
||||
SourceTy = Result;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -450,36 +440,32 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
|
|||
///
|
||||
/// \returns A suitable reference type, if there are no
|
||||
/// errors. Otherwise, returns a NULL type.
|
||||
QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,
|
||||
SourceLocation Loc, DeclarationName Entity) {
|
||||
QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
|
||||
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
|
||||
// reference to a type T, and attempt to create the type "lvalue
|
||||
// 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.
|
||||
QualType LVRT = Context.getLValueReferenceType(R->getPointeeType());
|
||||
return Context.getQualifiedType(LVRT, T.getQualifiers());
|
||||
}
|
||||
}
|
||||
if (T->isReferenceType()) {
|
||||
// C++ [dcl.ref]p4: There shall be no references to references.
|
||||
//
|
||||
// According to C++ DR 106, references to references are only
|
||||
// diagnosed when they are written directly (e.g., "int & &"),
|
||||
// but not when they happen via a typedef:
|
||||
//
|
||||
// typedef int& intref;
|
||||
// typedef intref& intref2;
|
||||
//
|
||||
// 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.
|
||||
return T;
|
||||
}
|
||||
|
||||
bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
|
||||
|
||||
// C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
|
||||
// reference to a type T, and attempt to create the type "lvalue
|
||||
// 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.
|
||||
|
||||
// C++ [dcl.ref]p4: There shall be no references to references.
|
||||
//
|
||||
// According to C++ DR 106, references to references are only
|
||||
// diagnosed when they are written directly (e.g., "int & &"),
|
||||
// but not when they happen via a typedef:
|
||||
//
|
||||
// typedef int& intref;
|
||||
// typedef intref& intref2;
|
||||
//
|
||||
// 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.
|
||||
|
||||
// C++ [dcl.ref]p1:
|
||||
// A declarator that specifies the type "reference to cv void"
|
||||
|
@ -511,7 +497,8 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,
|
|||
|
||||
// Handle restrict on references.
|
||||
if (LValueRef)
|
||||
return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals);
|
||||
return Context.getQualifiedType(
|
||||
Context.getLValueReferenceType(T, SpelledAsLValue), Quals);
|
||||
return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
|
||||
}
|
||||
|
||||
|
@ -717,7 +704,7 @@ QualType Sema::BuildFunctionType(QualType T,
|
|||
Invalid = true;
|
||||
}
|
||||
|
||||
ParamTypes[Idx] = adjustFunctionParamType(ParamType);
|
||||
ParamTypes[Idx] = ParamType;
|
||||
}
|
||||
|
||||
if (Invalid)
|
||||
|
@ -856,9 +843,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
// Determine the type of the declarator. Not all forms of declarator
|
||||
// have a type.
|
||||
QualType T;
|
||||
// The QualType referring to the type as written in source code. We can't use
|
||||
// T because it can change due to semantic analysis.
|
||||
QualType SourceTy;
|
||||
|
||||
switch (D.getKind()) {
|
||||
case Declarator::DK_Abstract:
|
||||
|
@ -872,7 +856,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
T = Context.DependentTy;
|
||||
} else {
|
||||
bool isInvalid = false;
|
||||
T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid, SourceTy);
|
||||
T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);
|
||||
if (isInvalid)
|
||||
D.setInvalidType(true);
|
||||
else if (OwnedDecl && DS.isTypeSpecOwned())
|
||||
|
@ -891,9 +875,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
break;
|
||||
}
|
||||
|
||||
if (SourceTy.isNull())
|
||||
SourceTy = T;
|
||||
|
||||
if (T == Context.UndeducedAutoTy) {
|
||||
int Error = -1;
|
||||
|
||||
|
@ -942,8 +923,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
if (D.getIdentifier())
|
||||
Name = D.getIdentifier();
|
||||
|
||||
bool ShouldBuildInfo = DInfo != 0;
|
||||
|
||||
// Walk the DeclTypeInfo, building the recursive type as we go.
|
||||
// DeclTypeInfos are ordered from the identifier out, which is
|
||||
// opposite of what we want :).
|
||||
|
@ -952,17 +931,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
switch (DeclType.Kind) {
|
||||
default: assert(0 && "Unknown decltype!");
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
if (ShouldBuildInfo) {
|
||||
if (SourceTy->isFunctionType())
|
||||
SourceTy
|
||||
= Context.getQualifiedType(Context.getBlockPointerType(SourceTy),
|
||||
Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals));
|
||||
else
|
||||
// If not function type Context::getBlockPointerType asserts,
|
||||
// so just give up.
|
||||
ShouldBuildInfo = false;
|
||||
}
|
||||
|
||||
// If blocks are disabled, emit an error.
|
||||
if (!LangOpts.Blocks)
|
||||
Diag(DeclType.Loc, diag::err_blocks_disable);
|
||||
|
@ -971,10 +939,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
Name);
|
||||
break;
|
||||
case DeclaratorChunk::Pointer:
|
||||
//FIXME: Use ObjCObjectPointer for info when appropriate.
|
||||
if (ShouldBuildInfo)
|
||||
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)) {
|
||||
|
@ -995,14 +959,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
Qualifiers Quals;
|
||||
if (DeclType.Ref.HasRestrict) Quals.addRestrict();
|
||||
|
||||
if (ShouldBuildInfo) {
|
||||
if (DeclType.Ref.LValueRef)
|
||||
SourceTy = Context.getLValueReferenceType(SourceTy);
|
||||
else
|
||||
SourceTy = Context.getRValueReferenceType(SourceTy);
|
||||
SourceTy = Context.getQualifiedType(SourceTy, Quals);
|
||||
}
|
||||
|
||||
// Verify that we're not building a reference to pointer to function with
|
||||
// exception specification.
|
||||
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
|
||||
|
@ -1015,11 +971,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
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);
|
||||
|
||||
// Verify that we're not building an array of pointers to function with
|
||||
// exception specification.
|
||||
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
|
||||
|
@ -1051,24 +1002,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
break;
|
||||
}
|
||||
case DeclaratorChunk::Function: {
|
||||
if (ShouldBuildInfo) {
|
||||
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
|
||||
llvm::SmallVector<QualType, 16> ArgTys;
|
||||
|
||||
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
|
||||
ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
|
||||
if (Param) {
|
||||
QualType ArgTy = adjustFunctionParamType(Param->getType());
|
||||
|
||||
ArgTys.push_back(ArgTy);
|
||||
}
|
||||
}
|
||||
SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(),
|
||||
ArgTys.size(),
|
||||
FTI.isVariadic,
|
||||
FTI.TypeQuals);
|
||||
}
|
||||
|
||||
// If the function declarator has a prototype (i.e. it is not () and
|
||||
// does not have a K&R-style identifier list), then the arguments are part
|
||||
// of the type, otherwise the argument list is ().
|
||||
|
@ -1137,6 +1070,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
} else if (FTI.ArgInfo[0].Param == 0) {
|
||||
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
|
||||
Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
|
||||
D.setInvalidType(true);
|
||||
} else {
|
||||
// Otherwise, we have a function with an argument list that is
|
||||
// potentially variadic.
|
||||
|
@ -1185,7 +1119,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
}
|
||||
}
|
||||
|
||||
ArgTys.push_back(adjustFunctionParamType(ArgTy));
|
||||
ArgTys.push_back(ArgTy);
|
||||
}
|
||||
|
||||
llvm::SmallVector<QualType, 4> Exceptions;
|
||||
|
@ -1234,13 +1168,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
if (ShouldBuildInfo) {
|
||||
QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy;
|
||||
SourceTy = Context.getQualifiedType(
|
||||
Context.getMemberPointerType(SourceTy, cls.getTypePtr()),
|
||||
Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals));
|
||||
}
|
||||
|
||||
if (!ClsType.isNull())
|
||||
T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
|
||||
DeclType.Loc, D.getIdentifier());
|
||||
|
@ -1293,8 +1220,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
if (const AttributeList *Attrs = D.getAttributes())
|
||||
ProcessTypeAttributeList(T, Attrs);
|
||||
|
||||
if (ShouldBuildInfo)
|
||||
*DInfo = GetDeclaratorInfoForDeclarator(D, SourceTy, Skip);
|
||||
if (DInfo) {
|
||||
if (D.isInvalidType())
|
||||
*DInfo = 0;
|
||||
else
|
||||
*DInfo = GetDeclaratorInfoForDeclarator(D, T, Skip);
|
||||
}
|
||||
|
||||
return T;
|
||||
}
|
||||
|
@ -1314,17 +1245,49 @@ namespace {
|
|||
}
|
||||
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
TL.setNameLoc(DS.getTypeSpecTypeLoc());
|
||||
}
|
||||
void VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) {
|
||||
assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
|
||||
TL.setLAngleLoc(DS.getProtocolLAngleLoc());
|
||||
TL.setRAngleLoc(DS.getSourceRange().getEnd());
|
||||
for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i)
|
||||
TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
|
||||
|
||||
TypeLoc BaseLoc = TL.getBaseTypeLoc();
|
||||
if (BaseLoc)
|
||||
if (DS.getProtocolQualifiers()) {
|
||||
assert(TL.getNumProtocols() > 0);
|
||||
assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
|
||||
TL.setLAngleLoc(DS.getProtocolLAngleLoc());
|
||||
TL.setRAngleLoc(DS.getSourceRange().getEnd());
|
||||
for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
|
||||
TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
|
||||
} else {
|
||||
assert(TL.getNumProtocols() == 0);
|
||||
TL.setLAngleLoc(SourceLocation());
|
||||
TL.setRAngleLoc(SourceLocation());
|
||||
}
|
||||
}
|
||||
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
|
||||
|
||||
TL.setStarLoc(SourceLocation());
|
||||
|
||||
if (DS.getProtocolQualifiers()) {
|
||||
assert(TL.getNumProtocols() > 0);
|
||||
assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
|
||||
TL.setHasProtocolsAsWritten(true);
|
||||
TL.setLAngleLoc(DS.getProtocolLAngleLoc());
|
||||
TL.setRAngleLoc(DS.getSourceRange().getEnd());
|
||||
for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
|
||||
TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
|
||||
|
||||
} else {
|
||||
assert(TL.getNumProtocols() == 0);
|
||||
TL.setHasProtocolsAsWritten(false);
|
||||
TL.setLAngleLoc(SourceLocation());
|
||||
TL.setRAngleLoc(SourceLocation());
|
||||
}
|
||||
|
||||
// This might not have been written with an inner type.
|
||||
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
|
||||
TL.setHasBaseTypeAsWritten(false);
|
||||
TL.getBaseTypeLoc().initialize(SourceLocation());
|
||||
} else {
|
||||
TL.setHasBaseTypeAsWritten(true);
|
||||
Visit(TL.getBaseTypeLoc());
|
||||
}
|
||||
}
|
||||
void VisitTypeLoc(TypeLoc TL) {
|
||||
// FIXME: add other typespec types and change this to an assert.
|
||||
|
@ -1353,6 +1316,10 @@ namespace {
|
|||
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
|
||||
assert(Chunk.Kind == DeclaratorChunk::Pointer);
|
||||
TL.setStarLoc(Chunk.Loc);
|
||||
TL.setHasBaseTypeAsWritten(true);
|
||||
TL.setHasProtocolsAsWritten(false);
|
||||
TL.setLAngleLoc(SourceLocation());
|
||||
TL.setRAngleLoc(SourceLocation());
|
||||
}
|
||||
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
|
||||
assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
|
||||
|
@ -1361,7 +1328,8 @@ namespace {
|
|||
}
|
||||
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
|
||||
assert(Chunk.Kind == DeclaratorChunk::Reference);
|
||||
assert(Chunk.Ref.LValueRef);
|
||||
// 'Amp' is misleading: this might have been originally
|
||||
/// spelled with AmpAmp.
|
||||
TL.setAmpLoc(Chunk.Loc);
|
||||
}
|
||||
void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
|
||||
|
@ -1381,12 +1349,9 @@ namespace {
|
|||
TL.setRParenLoc(Chunk.EndLoc);
|
||||
|
||||
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
|
||||
for (unsigned i = 0, e = FTI.NumArgs, tpi = 0; i != e; ++i) {
|
||||
for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
|
||||
ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
|
||||
if (Param) {
|
||||
assert(tpi < TL.getNumArgs());
|
||||
TL.setArg(tpi++, Param);
|
||||
}
|
||||
TL.setArg(tpi++, Param);
|
||||
}
|
||||
// FIXME: exception specs
|
||||
}
|
||||
|
|
|
@ -514,14 +514,6 @@ public:
|
|||
SourceRange(getDerived().getBaseLocation()));
|
||||
}
|
||||
|
||||
/// \brief Rebuild an objective C protocol list type.
|
||||
QualType RebuildObjCProtocolListType(QualType BaseType,
|
||||
ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
return SemaRef.Context.getObjCProtocolListType(BaseType, Protocols,
|
||||
NumProtocols);
|
||||
}
|
||||
|
||||
/// \brief Build a new nested-name-specifier given the prefix and an
|
||||
/// identifier that names the next step in the nested-name-specifier.
|
||||
///
|
||||
|
@ -2808,50 +2800,16 @@ template<typename Derived>
|
|||
QualType
|
||||
TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
|
||||
ObjCInterfaceTypeLoc TL) {
|
||||
return TransformTypeSpecType(TLB, TL);
|
||||
assert(false && "TransformObjCInterfaceType unimplemented");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType
|
||||
TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
|
||||
ObjCObjectPointerTypeLoc TL) {
|
||||
TransformPointerLikeType(ObjCObjectPointerType);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformObjCProtocolListType(
|
||||
TypeLocBuilder &TLB,
|
||||
ObjCProtocolListTypeLoc TL) {
|
||||
ObjCProtocolListType *T = TL.getTypePtr();
|
||||
QualType BaseType = T->getBaseType();
|
||||
if (!BaseType.isNull()) {
|
||||
BaseType = getDerived().TransformType(TLB, TL.getBaseTypeLoc());
|
||||
if (BaseType.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
||||
QualType Result = TL.getType();
|
||||
if (getDerived().AlwaysRebuild() ||
|
||||
BaseType != T->getBaseType()) {
|
||||
// TODO: transform these?
|
||||
llvm::SmallVector<ObjCProtocolDecl*,4> Protocols(T->getNumProtocols());
|
||||
std::copy(T->qual_begin(), T->qual_end(), Protocols.begin());
|
||||
Result = getDerived().RebuildObjCProtocolListType(BaseType,
|
||||
&Protocols[0],
|
||||
T->getNumProtocols());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
||||
ObjCProtocolListTypeLoc NewTL = TLB.push<ObjCProtocolListTypeLoc>(Result);
|
||||
NewTL.setLAngleLoc(TL.getLAngleLoc());
|
||||
NewTL.setRAngleLoc(TL.getRAngleLoc());
|
||||
|
||||
assert(NewTL.getNumProtocols() == TL.getNumProtocols());
|
||||
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
|
||||
NewTL.setProtocolLoc(i, TL.getProtocolLoc(i));
|
||||
|
||||
return Result;
|
||||
assert(false && "TransformObjCObjectPointerType unimplemented");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -155,7 +155,7 @@ typedef INTREF Func1(FLOAT, double);
|
|||
typedef float& Func2(int, double);
|
||||
|
||||
struct ConvertToFunc {
|
||||
operator Func1*(); // expected-note{{conversion candidate of type 'INTREF (*)(float, double)'}}
|
||||
operator Func1*(); // expected-note{{conversion candidate of type 'INTREF (*)(FLOAT, double)'}}
|
||||
operator Func2&(); // expected-note{{conversion candidate of type 'float &(&)(int, double)'}}
|
||||
void operator()();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue