[cfe-commits] r43432 - in /cfe/trunk: AST/Type.cpp include/clang/AST/Type.h

Chris Lattner sabre at nondot.org
Sun Oct 28 20:41:11 PDT 2007


Author: lattner
Date: Sun Oct 28 22:41:11 2007
New Revision: 43432

URL: http://llvm.org/viewvc/llvm-project?rev=43432&view=rev
Log:
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.

Modified:
    cfe/trunk/AST/Type.cpp
    cfe/trunk/include/clang/AST/Type.h

Modified: cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Type.cpp?rev=43432&r1=43431&r2=43432&view=diff

==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Sun Oct 28 22:41:11 2007
@@ -77,16 +77,35 @@
   return isa<ComplexType>(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<TypedefType>(this))
+    return TDT->LookThroughTypedefs().getTypePtr();
+  if (const TypeOfExpr *TOE = dyn_cast<TypeOfExpr>(this))
+    return TOE->getUnderlyingExpr()->getType().getTypePtr();
+  if (const TypeOfType *TOT = dyn_cast<TypeOfType>(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<BuiltinType>(this))
     return BTy;
-  
+
+  // If the canonical form of this type isn't a builtin type, reject it.
+  if (!isa<BuiltinType>(CanonicalType))
+    return 0;
+
   // If this is a typedef for a builtin type, strip the typedef off without
   // losing all typedef information.
-  if (isa<BuiltinType>(CanonicalType))
-    return cast<BuiltinType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  return getDesugaredType()->getAsBuiltinType();
 }
 
 const FunctionType *Type::getAsFunctionType() const {
@@ -94,11 +113,13 @@
   if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
     return FTy;
   
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<FunctionType>(CanonicalType))
+    return 0;
+  
   // If this is a typedef for a function type, strip the typedef off without
   // losing all typedef information.
-  if (isa<FunctionType>(CanonicalType))
-    return cast<FunctionType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  return getDesugaredType()->getAsFunctionType();
 }
 
 const PointerType *Type::getAsPointerType() const {
@@ -106,11 +127,13 @@
   if (const PointerType *PTy = dyn_cast<PointerType>(this))
     return PTy;
   
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<PointerType>(CanonicalType))
+    return 0;
+
   // If this is a typedef for a pointer type, strip the typedef off without
   // losing all typedef information.
-  if (isa<PointerType>(CanonicalType))
-    return cast<PointerType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  return getDesugaredType()->getAsPointerType();
 }
 
 const ReferenceType *Type::getAsReferenceType() const {
@@ -118,11 +141,13 @@
   if (const ReferenceType *RTy = dyn_cast<ReferenceType>(this))
     return RTy;
   
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<ReferenceType>(CanonicalType))
+    return 0;
+
   // If this is a typedef for a reference type, strip the typedef off without
   // losing all typedef information.
-  if (isa<ReferenceType>(CanonicalType))
-    return cast<ReferenceType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  return getDesugaredType()->getAsReferenceType();
 }
 
 const ArrayType *Type::getAsArrayType() const {
@@ -130,11 +155,13 @@
   if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
     return ATy;
   
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<ArrayType>(CanonicalType))
+    return 0;
+  
   // If this is a typedef for an array type, strip the typedef off without
   // losing all typedef information.
-  if (isa<ArrayType>(CanonicalType))
-    return cast<ArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  return getDesugaredType()->getAsArrayType();
 }
 
 const ConstantArrayType *Type::getAsConstantArrayType() const {
@@ -142,11 +169,13 @@
   if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
     return ATy;
   
-  // If this is a typedef for an array type, strip the typedef off without
-  // losing all typedef information.
-  if (isa<ConstantArrayType>(CanonicalType))
-    return cast<ConstantArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<ConstantArrayType>(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 @@
   if (const VariableArrayType *ATy = dyn_cast<VariableArrayType>(this))
     return ATy;
   
-  // If this is a typedef for an array type, strip the typedef off without
-  // losing all typedef information.
-  if (isa<VariableArrayType>(CanonicalType))
-    return cast<VariableArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<VariableArrayType>(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 @@
   if (const RecordType *RTy = dyn_cast<RecordType>(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<RecordType>(CanonicalType))
+    return 0;
+
+  // If this is a typedef for a record type, strip the typedef off without
   // losing all typedef information.
-  if (isa<RecordType>(CanonicalType))
-    return cast<RecordType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  return 0;
+  return getDesugaredType()->getAsRecordType();
 }
 
 const RecordType *Type::getAsStructureType() const {
@@ -197,11 +230,15 @@
     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<RecordType>(CanonicalType)) {
-    if (RT->getDecl()->getKind() == Decl::Struct)
-      return cast<RecordType>(cast<TypedefType>(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 @@
     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<RecordType>(CanonicalType)) {
-    if (RT->getDecl()->getKind() == Decl::Union)
-      return cast<RecordType>(cast<TypedefType>(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 @@
   if (const ComplexType *CTy = dyn_cast<ComplexType>(this))
     return CTy;
   
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<ComplexType>(CanonicalType))
+    return 0;
+
   // If this is a typedef for a complex type, strip the typedef off without
   // losing all typedef information.
-  if (isa<ComplexType>(CanonicalType))
-    return cast<ComplexType>(cast<TypedefType>(this)->LookThroughTypedefs());
-  
-  return 0;
+  return getDesugaredType()->getAsComplexType();
 }
 
 const VectorType *Type::getAsVectorType() const {
@@ -239,12 +280,13 @@
   if (const VectorType *VTy = dyn_cast<VectorType>(this))
     return VTy;
   
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<VectorType>(CanonicalType))
+    return 0;
+
   // If this is a typedef for a vector type, strip the typedef off without
   // losing all typedef information.
-  if (isa<VectorType>(CanonicalType))
-    return cast<VectorType>(cast<TypedefType>(this)->LookThroughTypedefs());
-
-  return 0;
+  return getDesugaredType()->getAsVectorType();
 }
 
 const OCUVectorType *Type::getAsOCUVectorType() const {
@@ -252,12 +294,13 @@
   if (const OCUVectorType *VTy = dyn_cast<OCUVectorType>(this))
     return VTy;
   
-  // If this is a typedef for an OpenCU vector type, strip the typedef off 
-  // without losing all typedef information.
-  if (isa<OCUVectorType>(CanonicalType))
-    return cast<OCUVectorType>(cast<TypedefType>(this)->LookThroughTypedefs());
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<OCUVectorType>(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 {

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=43432&r1=43431&r2=43432&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sun Oct 28 22:41:11 2007
@@ -170,8 +170,6 @@
   
   /// ReadOwned - Deserialize a QualType that owns the underlying Thpe*.
   void ReadOwned(llvm::Deserializer& S);
-  
-private:
 };
 
 } // end clang.
@@ -318,6 +316,14 @@
   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
 





More information about the cfe-commits mailing list