forked from OSchip/llvm-project
add a common base class "PointerLikeType" for PointerType and ReferenceType,
allowing them to be treated the same in some contexts. A suggestion for a better name is welcome :) llvm-svn: 49100
This commit is contained in:
parent
be3d44c3cb
commit
db5f1fa3d8
|
@ -38,6 +38,7 @@ namespace clang {
|
|||
class ObjCMethodDecl;
|
||||
class Expr;
|
||||
class SourceLocation;
|
||||
class PointerLikeType;
|
||||
class PointerType;
|
||||
class ReferenceType;
|
||||
class VectorType;
|
||||
|
@ -303,9 +304,10 @@ public:
|
|||
// Type Predicates: Check to see if this type is structurally the specified
|
||||
// type, ignoring typedefs and qualifiers.
|
||||
bool isFunctionType() const;
|
||||
bool isPointerLikeType() const; // Pointer or Reference.
|
||||
bool isPointerType() const;
|
||||
bool isFunctionPointerType() const;
|
||||
bool isReferenceType() const;
|
||||
bool isFunctionPointerType() const;
|
||||
bool isArrayType() const;
|
||||
bool isRecordType() const;
|
||||
bool isStructureType() const;
|
||||
|
@ -321,6 +323,7 @@ public:
|
|||
// the best type we can.
|
||||
const BuiltinType *getAsBuiltinType() const;
|
||||
const FunctionType *getAsFunctionType() const;
|
||||
const PointerLikeType *getAsPointerLikeType() const; // Pointer or Reference.
|
||||
const PointerType *getAsPointerType() const;
|
||||
const ReferenceType *getAsReferenceType() const;
|
||||
const ArrayType *getAsArrayType() const;
|
||||
|
@ -488,22 +491,35 @@ protected:
|
|||
friend class Type;
|
||||
};
|
||||
|
||||
/// PointerLikeType - Common base class for pointers and references.
|
||||
///
|
||||
class PointerLikeType : public Type {
|
||||
QualType PointeeType;
|
||||
protected:
|
||||
PointerLikeType(TypeClass K, QualType Pointee, QualType CanonicalPtr) :
|
||||
Type(K, CanonicalPtr), PointeeType(Pointee) {
|
||||
}
|
||||
public:
|
||||
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Pointer || T->getTypeClass() == Reference;
|
||||
}
|
||||
static bool classof(const PointerLikeType *) { return true; }
|
||||
};
|
||||
|
||||
/// PointerType - C99 6.7.5.1 - Pointer Declarators.
|
||||
///
|
||||
class PointerType : public Type, public llvm::FoldingSetNode {
|
||||
QualType PointeeType;
|
||||
class PointerType : public PointerLikeType, public llvm::FoldingSetNode {
|
||||
PointerType(QualType Pointee, QualType CanonicalPtr) :
|
||||
Type(Pointer, CanonicalPtr), PointeeType(Pointee) {
|
||||
PointerLikeType(Pointer, Pointee, CanonicalPtr) {
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
QualType getPointeeType() const { return PointeeType; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getPointeeType());
|
||||
}
|
||||
|
@ -522,19 +538,16 @@ protected:
|
|||
|
||||
/// ReferenceType - C++ 8.3.2 - Reference Declarators.
|
||||
///
|
||||
class ReferenceType : public Type, public llvm::FoldingSetNode {
|
||||
QualType ReferenceeType;
|
||||
class ReferenceType : public PointerLikeType, public llvm::FoldingSetNode {
|
||||
ReferenceType(QualType Referencee, QualType CanonicalRef) :
|
||||
Type(Reference, CanonicalRef), ReferenceeType(Referencee) {
|
||||
PointerLikeType(Reference, Referencee, CanonicalRef) {
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
QualType getReferenceeType() const { return ReferenceeType; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getReferenceeType());
|
||||
Profile(ID, getPointeeType());
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) {
|
||||
ID.AddPointer(Referencee.getAsOpaquePtr());
|
||||
|
@ -1139,15 +1152,18 @@ inline bool Type::isFunctionType() const {
|
|||
inline bool Type::isPointerType() const {
|
||||
return isa<PointerType>(CanonicalType.getUnqualifiedType());
|
||||
}
|
||||
inline bool Type::isReferenceType() const {
|
||||
return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
|
||||
}
|
||||
inline bool Type::isPointerLikeType() const {
|
||||
return isa<PointerLikeType>(CanonicalType.getUnqualifiedType());
|
||||
}
|
||||
inline bool Type::isFunctionPointerType() const {
|
||||
if (const PointerType* T = getAsPointerType())
|
||||
return T->getPointeeType()->isFunctionType();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
inline bool Type::isReferenceType() const {
|
||||
return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
|
||||
}
|
||||
inline bool Type::isArrayType() const {
|
||||
return isa<ArrayType>(CanonicalType.getUnqualifiedType());
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ ASTContext::getTypeInfo(QualType T) {
|
|||
// of the referenced type." C++98 5.3.3p2: expr.sizeof.
|
||||
// FIXME: This is wrong for struct layout: a reference in a struct has
|
||||
// pointer size.
|
||||
return getTypeInfo(cast<ReferenceType>(T)->getReferenceeType());
|
||||
return getTypeInfo(cast<ReferenceType>(T)->getPointeeType());
|
||||
|
||||
case Type::Complex: {
|
||||
// Complex types have the same alignment as their elements, but twice the
|
||||
|
@ -1725,12 +1725,12 @@ bool ASTContext::referenceTypesAreCompatible(QualType lhs, QualType rhs) {
|
|||
QualType ltype = lhs;
|
||||
|
||||
if (lhs->isReferenceType())
|
||||
ltype = cast<ReferenceType>(lhs.getCanonicalType())->getReferenceeType();
|
||||
ltype = cast<ReferenceType>(lhs.getCanonicalType())->getPointeeType();
|
||||
|
||||
QualType rtype = rhs;
|
||||
|
||||
if (rhs->isReferenceType())
|
||||
rtype = cast<ReferenceType>(rhs.getCanonicalType())->getReferenceeType();
|
||||
rtype = cast<ReferenceType>(rhs.getCanonicalType())->getPointeeType();
|
||||
|
||||
return typesAreCompatible(ltype, rtype);
|
||||
}
|
||||
|
@ -1817,9 +1817,9 @@ bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) {
|
|||
// designates the object or function denoted by the reference, and the
|
||||
// expression is an lvalue.
|
||||
if (ReferenceType *RT = dyn_cast<ReferenceType>(lcanon))
|
||||
lcanon = RT->getReferenceeType();
|
||||
lcanon = RT->getPointeeType();
|
||||
if (ReferenceType *RT = dyn_cast<ReferenceType>(rcanon))
|
||||
rcanon = RT->getReferenceeType();
|
||||
rcanon = RT->getPointeeType();
|
||||
|
||||
Type::TypeClass LHSClass = lcanon->getTypeClass();
|
||||
Type::TypeClass RHSClass = rcanon->getTypeClass();
|
||||
|
|
|
@ -155,6 +155,24 @@ const FunctionType *Type::getAsFunctionType() const {
|
|||
return getDesugaredType()->getAsFunctionType();
|
||||
}
|
||||
|
||||
const PointerLikeType *Type::getAsPointerLikeType() const {
|
||||
// If this is directly a pointer-like type, return it.
|
||||
if (const PointerLikeType *PTy = dyn_cast<PointerLikeType>(this))
|
||||
return PTy;
|
||||
|
||||
// If the canonical form of this type isn't the right kind, reject it.
|
||||
if (!isa<PointerLikeType>(CanonicalType)) {
|
||||
// Look through type qualifiers
|
||||
if (isa<PointerLikeType>(CanonicalType.getUnqualifiedType()))
|
||||
return CanonicalType.getUnqualifiedType()->getAsPointerLikeType();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If this is a typedef for a pointer type, strip the typedef off without
|
||||
// losing all typedef information.
|
||||
return getDesugaredType()->getAsPointerLikeType();
|
||||
}
|
||||
|
||||
const PointerType *Type::getAsPointerType() const {
|
||||
// If this is directly a pointer type, return it.
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(this))
|
||||
|
@ -796,10 +814,10 @@ void PointerType::getAsStringInternal(std::string &S) const {
|
|||
|
||||
// Handle things like 'int (*A)[4];' correctly.
|
||||
// FIXME: this should include vectors, but vectors use attributes I guess.
|
||||
if (isa<ArrayType>(PointeeType.getTypePtr()))
|
||||
if (isa<ArrayType>(getPointeeType()))
|
||||
S = '(' + S + ')';
|
||||
|
||||
PointeeType.getAsStringInternal(S);
|
||||
getPointeeType().getAsStringInternal(S);
|
||||
}
|
||||
|
||||
void ReferenceType::getAsStringInternal(std::string &S) const {
|
||||
|
@ -807,10 +825,10 @@ void ReferenceType::getAsStringInternal(std::string &S) const {
|
|||
|
||||
// Handle things like 'int (&A)[4];' correctly.
|
||||
// FIXME: this should include vectors, but vectors use attributes I guess.
|
||||
if (isa<ArrayType>(ReferenceeType.getTypePtr()))
|
||||
if (isa<ArrayType>(getPointeeType()))
|
||||
S = '(' + S + ')';
|
||||
|
||||
ReferenceeType.getAsStringInternal(S);
|
||||
getPointeeType().getAsStringInternal(S);
|
||||
}
|
||||
|
||||
void ConstantArrayType::getAsStringInternal(std::string &S) const {
|
||||
|
|
|
@ -213,7 +213,7 @@ public:
|
|||
return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), false);
|
||||
}
|
||||
Value *EmitSizeAlignOf(QualType TypeToSize, QualType RetType,
|
||||
bool isSizeOf);
|
||||
bool isSizeOf);
|
||||
Value *VisitUnaryReal (const UnaryOperator *E);
|
||||
Value *VisitUnaryImag (const UnaryOperator *E);
|
||||
Value *VisitUnaryExtension(const UnaryOperator *E) {
|
||||
|
@ -537,7 +537,7 @@ Value *ScalarExprEmitter::VisitImplicitCastExpr(const ImplicitCastExpr *E) {
|
|||
|
||||
} else if (E->getType()->isReferenceType()) {
|
||||
assert(cast<ReferenceType>(E->getType().getCanonicalType())->
|
||||
getReferenceeType() ==
|
||||
getPointeeType() ==
|
||||
Op->getType().getCanonicalType() && "Incompatible types!");
|
||||
|
||||
return EmitLValue(Op).getAddress();
|
||||
|
|
|
@ -206,15 +206,11 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
|||
ConvertType(cast<ComplexType>(Ty).getElementType());
|
||||
return llvm::StructType::get(EltTy, EltTy, NULL);
|
||||
}
|
||||
case Type::Reference:
|
||||
case Type::Pointer: {
|
||||
const PointerType &P = cast<PointerType>(Ty);
|
||||
QualType ETy = P.getPointeeType();
|
||||
QualType ETy = cast<PointerLikeType>(Ty).getPointeeType();
|
||||
return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace());
|
||||
}
|
||||
case Type::Reference: {
|
||||
const ReferenceType &R = cast<ReferenceType>(Ty);
|
||||
return llvm::PointerType::getUnqual(ConvertType(R.getReferenceeType()));
|
||||
}
|
||||
|
||||
case Type::VariableArray: {
|
||||
const VariableArrayType &A = cast<VariableArrayType>(Ty);
|
||||
|
|
|
@ -154,28 +154,23 @@ QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) {
|
|||
// or incomplete types shall not be restrict-qualified." C++ also allows
|
||||
// restrict-qualified references.
|
||||
if (TypeQuals & QualType::Restrict) {
|
||||
QualType EltTy;
|
||||
if (const PointerType *PT = Result->getAsPointerType())
|
||||
EltTy = PT->getPointeeType();
|
||||
else if (const ReferenceType *RT = Result->getAsReferenceType())
|
||||
EltTy = RT->getReferenceeType();
|
||||
else {
|
||||
if (const PointerLikeType *PT = Result->getAsPointerLikeType()) {
|
||||
QualType EltTy = PT->getPointeeType();
|
||||
|
||||
// If we have a pointer or reference, the pointee must have an object or
|
||||
// incomplete type.
|
||||
if (!EltTy->isIncompleteOrObjectType()) {
|
||||
Diag(DS.getRestrictSpecLoc(),
|
||||
diag::err_typecheck_invalid_restrict_invalid_pointee,
|
||||
EltTy.getAsString(), DS.getSourceRange());
|
||||
TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
|
||||
}
|
||||
} else {
|
||||
Diag(DS.getRestrictSpecLoc(),
|
||||
diag::err_typecheck_invalid_restrict_not_pointer,
|
||||
Result.getAsString(), DS.getSourceRange());
|
||||
TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
|
||||
}
|
||||
|
||||
// If we have a pointer or reference, the pointee must have an object or
|
||||
// incomplete type.
|
||||
if (!EltTy.isNull() && !EltTy->isIncompleteOrObjectType()) {
|
||||
Diag(DS.getRestrictSpecLoc(),
|
||||
diag::err_typecheck_invalid_restrict_invalid_pointee,
|
||||
EltTy.getAsString(), DS.getSourceRange());
|
||||
EltTy = QualType();
|
||||
}
|
||||
|
||||
if (EltTy.isNull()) // Invalid restrict: remove the restrict qualifier.
|
||||
TypeQuals &= ~QualType::Restrict;
|
||||
}
|
||||
|
||||
// Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
|
||||
|
@ -249,7 +244,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||
Diag(DeclType.Loc, diag::err_illegal_decl_reference_to_reference,
|
||||
D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
|
||||
D.setInvalidType(true);
|
||||
T = RT->getReferenceeType();
|
||||
T = RT->getPointeeType();
|
||||
}
|
||||
|
||||
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
|
||||
|
@ -299,7 +294,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||
// C++ 8.3.2p4: There shall be no ... arrays of references ...
|
||||
Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_references,
|
||||
D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
|
||||
T = RT->getReferenceeType();
|
||||
T = RT->getPointeeType();
|
||||
D.setInvalidType(true);
|
||||
} else if (const RecordType *EltTy = T->getAsRecordType()) {
|
||||
// If the element type is a struct or union that contains a variadic
|
||||
|
|
Loading…
Reference in New Issue