From: Chris Lattner Date: Mon, 29 Oct 2007 03:41:11 +0000 (+0000) Subject: Fix a major bug in the Type::getAs*Type methods: they didn't strip off X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dea6146deede4b89a1757d46cd92ebf158659c25;p=clang Fix a major bug in the Type::getAs*Type methods: they didn't strip off typeof(type) and typeof(expr) correctly. Now provide a single point of contact (Type::getDesugaredType) for doing the shallow stripping we need. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43432 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Type.cpp b/AST/Type.cpp index bde2eb5d1d..f562376de6 100644 --- a/AST/Type.cpp +++ b/AST/Type.cpp @@ -77,16 +77,35 @@ bool Type::isComplexType() const { return isa(CanonicalType); } +/// getDesugaredType - Return the specified type with any "sugar" removed from +/// type type. This takes off typedefs, typeof's etc. If the outer level of +/// the type is already concrete, it returns it unmodified. This is similar +/// to getting the canonical type, but it doesn't remove *all* typedefs. For +/// example, it return "T*" as "T*", (not as "int*"), because the pointer is +/// concrete. +const Type *Type::getDesugaredType() const { + if (const TypedefType *TDT = dyn_cast(this)) + return TDT->LookThroughTypedefs().getTypePtr(); + if (const TypeOfExpr *TOE = dyn_cast(this)) + return TOE->getUnderlyingExpr()->getType().getTypePtr(); + if (const TypeOfType *TOT = dyn_cast(this)) + return TOT->getUnderlyingType().getTypePtr(); + return this; +} + + const BuiltinType *Type::getAsBuiltinType() const { // If this is directly a builtin type, return it. if (const BuiltinType *BTy = dyn_cast(this)) return BTy; - + + // If the canonical form of this type isn't a builtin type, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for a builtin type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + return getDesugaredType()->getAsBuiltinType(); } const FunctionType *Type::getAsFunctionType() const { @@ -94,11 +113,13 @@ const FunctionType *Type::getAsFunctionType() const { if (const FunctionType *FTy = dyn_cast(this)) return FTy; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for a function type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + return getDesugaredType()->getAsFunctionType(); } const PointerType *Type::getAsPointerType() const { @@ -106,11 +127,13 @@ const PointerType *Type::getAsPointerType() const { if (const PointerType *PTy = dyn_cast(this)) return PTy; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for a pointer type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + return getDesugaredType()->getAsPointerType(); } const ReferenceType *Type::getAsReferenceType() const { @@ -118,11 +141,13 @@ const ReferenceType *Type::getAsReferenceType() const { if (const ReferenceType *RTy = dyn_cast(this)) return RTy; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for a reference type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + return getDesugaredType()->getAsReferenceType(); } const ArrayType *Type::getAsArrayType() const { @@ -130,11 +155,13 @@ const ArrayType *Type::getAsArrayType() const { if (const ArrayType *ATy = dyn_cast(this)) return ATy; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for an array type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + return getDesugaredType()->getAsArrayType(); } const ConstantArrayType *Type::getAsConstantArrayType() const { @@ -142,11 +169,13 @@ const ConstantArrayType *Type::getAsConstantArrayType() const { if (const ConstantArrayType *ATy = dyn_cast(this)) return ATy; - // If this is a typedef for an array type, strip the typedef off without - // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + + // If this is a typedef for a constant array type, strip the typedef off + // without losing all typedef information. + return getDesugaredType()->getAsConstantArrayType(); } const VariableArrayType *Type::getAsVariableArrayType() const { @@ -154,11 +183,13 @@ const VariableArrayType *Type::getAsVariableArrayType() const { if (const VariableArrayType *ATy = dyn_cast(this)) return ATy; - // If this is a typedef for an array type, strip the typedef off without - // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + + // If this is a typedef for a variable array type, strip the typedef off + // without losing all typedef information. + return getDesugaredType()->getAsVariableArrayType(); } /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array @@ -184,11 +215,13 @@ const RecordType *Type::getAsRecordType() const { if (const RecordType *RTy = dyn_cast(this)) return RTy; - // If this is a typedef for an record type, strip the typedef off without + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + + // If this is a typedef for a record type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - return 0; + return getDesugaredType()->getAsRecordType(); } const RecordType *Type::getAsStructureType() const { @@ -197,11 +230,15 @@ const RecordType *Type::getAsStructureType() const { if (RT->getDecl()->getKind() == Decl::Struct) return RT; } - // If this is a typedef for a structure type, strip the typedef off without - // losing all typedef information. + + // If the canonical form of this type isn't the right kind, reject it. if (const RecordType *RT = dyn_cast(CanonicalType)) { - if (RT->getDecl()->getKind() == Decl::Struct) - return cast(cast(this)->LookThroughTypedefs()); + if (RT->getDecl()->getKind() != Decl::Struct) + return 0; + + // If this is a typedef for a structure type, strip the typedef off without + // losing all typedef information. + return getDesugaredType()->getAsStructureType(); } return 0; } @@ -212,11 +249,14 @@ const RecordType *Type::getAsUnionType() const { if (RT->getDecl()->getKind() == Decl::Union) return RT; } - // If this is a typedef for a union type, strip the typedef off without - // losing all typedef information. + // If the canonical form of this type isn't the right kind, reject it. if (const RecordType *RT = dyn_cast(CanonicalType)) { - if (RT->getDecl()->getKind() == Decl::Union) - return cast(cast(this)->LookThroughTypedefs()); + if (RT->getDecl()->getKind() != Decl::Union) + return 0; + + // If this is a typedef for a union type, strip the typedef off without + // losing all typedef information. + return getDesugaredType()->getAsUnionType(); } return 0; } @@ -226,12 +266,13 @@ const ComplexType *Type::getAsComplexType() const { if (const ComplexType *CTy = dyn_cast(this)) return CTy; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for a complex type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - - return 0; + return getDesugaredType()->getAsComplexType(); } const VectorType *Type::getAsVectorType() const { @@ -239,12 +280,13 @@ const VectorType *Type::getAsVectorType() const { if (const VectorType *VTy = dyn_cast(this)) return VTy; + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; + // If this is a typedef for a vector type, strip the typedef off without // losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); - - return 0; + return getDesugaredType()->getAsVectorType(); } const OCUVectorType *Type::getAsOCUVectorType() const { @@ -252,12 +294,13 @@ const OCUVectorType *Type::getAsOCUVectorType() const { if (const OCUVectorType *VTy = dyn_cast(this)) return VTy; - // If this is a typedef for an OpenCU vector type, strip the typedef off - // without losing all typedef information. - if (isa(CanonicalType)) - return cast(cast(this)->LookThroughTypedefs()); + // If the canonical form of this type isn't the right kind, reject it. + if (!isa(CanonicalType)) + return 0; - return 0; + // If this is a typedef for an ocuvector type, strip the typedef off without + // losing all typedef information. + return getDesugaredType()->getAsOCUVectorType(); } bool Type::isIntegerType() const { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index e62264b728..3a99e2b484 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -170,8 +170,6 @@ public: /// ReadOwned - Deserialize a QualType that owns the underlying Thpe*. void ReadOwned(llvm::Deserializer& S); - -private: }; } // end clang. @@ -318,6 +316,14 @@ public: const ComplexType *getAsComplexType() const; const OCUVectorType *getAsOCUVectorType() const; // OCU vector type. + /// getDesugaredType - Return the specified type with any "sugar" removed from + /// type type. This takes off typedefs, typeof's etc. If the outer level of + /// the type is already concrete, it returns it unmodified. This is similar + /// to getting the canonical type, but it doesn't remove *all* typedefs. For + /// example, it return "T*" as "T*", (not as "int*"), because the pointer is + /// concrete. + const Type *getDesugaredType() const; + /// More type predicates useful for type checking/promotion bool isPromotableIntegerType() const; // C99 6.3.1.1p2