diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index de3f6bda50c5..4d228776df9f 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -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(CanonicalType.getUnqualifiedType()); } +inline bool Type::isReferenceType() const { + return isa(CanonicalType.getUnqualifiedType()); +} +inline bool Type::isPointerLikeType() const { + return isa(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(CanonicalType.getUnqualifiedType()); -} inline bool Type::isArrayType() const { return isa(CanonicalType.getUnqualifiedType()); } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ce2e58fa3546..d716917b9ce4 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -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(T)->getReferenceeType()); + return getTypeInfo(cast(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(lhs.getCanonicalType())->getReferenceeType(); + ltype = cast(lhs.getCanonicalType())->getPointeeType(); QualType rtype = rhs; if (rhs->isReferenceType()) - rtype = cast(rhs.getCanonicalType())->getReferenceeType(); + rtype = cast(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(lcanon)) - lcanon = RT->getReferenceeType(); + lcanon = RT->getPointeeType(); if (ReferenceType *RT = dyn_cast(rcanon)) - rcanon = RT->getReferenceeType(); + rcanon = RT->getPointeeType(); Type::TypeClass LHSClass = lcanon->getTypeClass(); Type::TypeClass RHSClass = rcanon->getTypeClass(); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 9411cd8be645..40b376bbd90d 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -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(this)) + return PTy; + + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) { + // Look through type qualifiers + if (isa(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(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(PointeeType.getTypePtr())) + if (isa(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(ReferenceeType.getTypePtr())) + if (isa(getPointeeType())) S = '(' + S + ')'; - ReferenceeType.getAsStringInternal(S); + getPointeeType().getAsStringInternal(S); } void ConstantArrayType::getAsStringInternal(std::string &S) const { diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 9497ece6fbd4..cc7d8e97e481 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -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(E->getType().getCanonicalType())-> - getReferenceeType() == + getPointeeType() == Op->getType().getCanonicalType() && "Incompatible types!"); return EmitLValue(Op).getAddress(); diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index a16543eebeb7..4e8d46c7dd50 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -206,15 +206,11 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { ConvertType(cast(Ty).getElementType()); return llvm::StructType::get(EltTy, EltTy, NULL); } + case Type::Reference: case Type::Pointer: { - const PointerType &P = cast(Ty); - QualType ETy = P.getPointeeType(); + QualType ETy = cast(Ty).getPointeeType(); return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace()); } - case Type::Reference: { - const ReferenceType &R = cast(Ty); - return llvm::PointerType::getUnqual(ConvertType(R.getReferenceeType())); - } case Type::VariableArray: { const VariableArrayType &A = cast(Ty); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 76bb63b1add9..ca56c56dd9ad 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -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