[cfe-commits] r54317 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Expr.cpp lib/AST/Type.cpp lib/CodeGen/CGDebugInfo.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenModule.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaInit.cpp test/Sema/typedef-retain.c

Chris Lattner sabre at nondot.org
Mon Aug 4 00:31:18 PDT 2008


Author: lattner
Date: Mon Aug  4 02:31:14 2008
New Revision: 54317

URL: http://llvm.org/viewvc/llvm-project?rev=54317&view=rev
Log:

Finally fix PR2189.  This makes a fairly invasive but important change to
move getAsArrayType into ASTContext instead of being a method on type.
This is required because getAsArrayType(const AT), where AT is a typedef
for "int[10]" needs to return ArrayType(const int, 10).

Fixing this greatly simplifies getArrayDecayedType, which is a good sign.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Sema/typedef-retain.c

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug  4 02:31:14 2008
@@ -253,7 +253,7 @@
 
   // Return the ObjC type encoding for a given type.
   void getObjCEncodingForType(QualType t, std::string &S, 
-                              llvm::SmallVector<const RecordType *, 8> &RT) const;
+                              llvm::SmallVector<const RecordType*,8> &RT) const;
   
   // Put the string version of type qualifiers into S.
   void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, 
@@ -339,6 +339,21 @@
   /// for exact equality with a simple pointer comparison.
   QualType getCanonicalType(QualType T);
   
+  /// Type Query functions.  If the type is an instance of the specified class,
+  /// return the Type pointer for the underlying maximally pretty type.  This
+  /// is a member of ASTContext because this may need to do some amount of
+  /// canonicalization, e.g. to move type qualifiers into the element type.
+  const ArrayType *getAsArrayType(QualType T);
+  const ConstantArrayType *getAsConstantArrayType(QualType T) {
+    return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
+  }
+  const VariableArrayType *getAsVariableArrayType(QualType T) {
+    return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
+  }
+  const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
+    return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
+  }
+  
   /// getArrayDecayedType - Return the properly qualified result of decaying the
   /// specified array type to a pointer.  This operation is non-trivial when
   /// handling typedefs etc.  The canonical type of "T" must be an array type,

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

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Aug  4 02:31:14 2008
@@ -143,6 +143,9 @@
   QualType getQualifiedType(unsigned TQs) const {
     return QualType(getTypePtr(), TQs);
   }
+  QualType getWithAdditionalQualifiers(unsigned TQs) const {
+    return QualType(getTypePtr(), TQs|getCVRQualifiers());
+  }
   
   inline QualType getUnqualifiedType() const;
   
@@ -285,10 +288,6 @@
   /// types that have a non-constant expression. This does not include "[]".
   bool isVariablyModifiedType() const;
   
-  /// isIncompleteArrayType (C99 6.2.5p22) - Return true for variable array
-  /// types that don't have any expression ("[]").
-  bool isIncompleteArrayType() const;
-  
   /// Helper methods to distinguish type categories. All type predicates
   /// operate on the canonical type, ignoring typedefs and qualifiers.
   
@@ -322,6 +321,9 @@
   bool isReferenceType() const;
   bool isFunctionPointerType() const;
   bool isArrayType() const;
+  bool isConstantArrayType() const;
+  bool isIncompleteArrayType() const;
+  bool isVariableArrayType() const;
   bool isRecordType() const;
   bool isClassType() const;   
   bool isStructureType() const;   
@@ -342,12 +344,9 @@
   const PointerLikeType *getAsPointerLikeType() const; // Pointer or Reference.
   const PointerType *getAsPointerType() const;
   const ReferenceType *getAsReferenceType() const;
-  const ArrayType *getAsArrayType() const;
-  const ConstantArrayType *getAsConstantArrayType() const;
-  const VariableArrayType *getAsVariableArrayType() const;
-  const IncompleteArrayType *getAsIncompleteArrayType() const;
   const RecordType *getAsRecordType() const;
   const RecordType *getAsStructureType() const;
+  /// NOTE: getAsArrayType* are methods on ASTContext.
   const TypedefType *getAsTypedefType() const;
   const RecordType *getAsUnionType() const;
   const EnumType *getAsEnumType() const;
@@ -358,11 +357,17 @@
   const ObjCInterfaceType *getAsObjCInterfaceType() const;
   const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
   const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
-
+  
   /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
   /// interface, return the interface type, otherwise return null.
   const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
 
+  /// getArrayElementTypeNoTypeQual - If this is an array type, return the
+  /// element type of the array, potentially with type qualifiers missing.
+  /// This method should never be used when type qualifiers are meaningful.
+  const Type *getArrayElementTypeNoTypeQual() const;
+  
+
   
   /// getDesugaredType - Return the specified type with any "sugar" removed from
   /// the type.  This takes off typedefs, typeof's etc.  If the outer level of
@@ -370,7 +375,7 @@
   /// to getting the canonical type, but it doesn't remove *all* typedefs.  For
   /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
   /// concrete.
-  const Type *getDesugaredType() const;
+  QualType getDesugaredType() const;
   
   /// More type predicates useful for type checking/promotion
   bool isPromotableIntegerType() const; // C99 6.3.1.1p2
@@ -391,11 +396,8 @@
   /// according to the rules of C99 6.7.5p3.  It is not legal to call this on
   /// incomplete types.
   bool isConstantSizeType() const;
-private:  
+
   QualType getCanonicalTypeInternal() const { return CanonicalType; }
-  friend class QualType;
-  friend class TypedefType;
-public:
   void dump() const;
   virtual void getAsStringInternal(std::string &InnerString) const = 0;
   static bool classof(const Type *) { return true; }
@@ -619,14 +621,6 @@
   }
   unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
   
-  QualType getBaseType() const {
-    const ArrayType *AT;
-    QualType ElmtType = getElementType();
-    // If we have a multi-dimensional array, navigate to the base type.
-    while ((AT = ElmtType->getAsArrayType()))
-      ElmtType = AT->getElementType();
-    return ElmtType;
-  }
   static bool classof(const Type *T) {
     return T->getTypeClass() == ConstantArray ||
            T->getTypeClass() == VariableArray ||
@@ -646,19 +640,7 @@
     : ArrayType(ConstantArray, et, can, sm, tq), Size(sz) {}
   friend class ASTContext;  // ASTContext creates these.
 public:
-  llvm::APInt getSize() const { return Size; }
-  int getMaximumElements() const {
-    QualType ElmtType = getElementType();
-    int maxElements = static_cast<int>(getSize().getZExtValue());
-
-    const ConstantArrayType *CAT;
-    // If we have a multi-dimensional array, include it's elements.
-    while ((CAT = ElmtType->getAsConstantArrayType())) {
-      ElmtType = CAT->getElementType();
-      maxElements *= static_cast<int>(CAT->getSize().getZExtValue());
-    }
-    return maxElements;
-  }
+  const llvm::APInt &getSize() const { return Size; }
   virtual void getAsStringInternal(std::string &InnerString) const;
   
   void Profile(llvm::FoldingSetNodeID &ID) {
@@ -740,7 +722,7 @@
   virtual void Destroy(ASTContext& C);
 
 public:
-  const Expr *getSizeExpr() const { 
+  Expr *getSizeExpr() const { 
     // We use C-style casts instead of cast<> here because we do not wish
     // to have a dependency of Type.h on Stmt.h/Expr.h.
     return (Expr*) SizeExpr;
@@ -1274,7 +1256,7 @@
 inline unsigned QualType::getAddressSpace() const {
   QualType CT = getTypePtr()->getCanonicalTypeInternal();
   if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
-    return AT->getBaseType().getAddressSpace();
+    return AT->getElementType().getAddressSpace();
   if (const RecordType *RT = dyn_cast<RecordType>(CT))
     return RT->getAddressSpace();
   if (const ASQualType *ASQT = dyn_cast<ASQualType>(CT))
@@ -1291,7 +1273,8 @@
   return 0;
 }
   
-  
+// NOTE: All of these methods use "getUnqualifiedType" to strip off address
+// space qualifiers if present.
 inline bool Type::isFunctionType() const {
   return isa<FunctionType>(CanonicalType.getUnqualifiedType());
 }
@@ -1313,11 +1296,20 @@
 inline bool Type::isArrayType() const {
   return isa<ArrayType>(CanonicalType.getUnqualifiedType());
 }
+inline bool Type::isConstantArrayType() const {
+  return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isIncompleteArrayType() const {
+  return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isVariableArrayType() const {
+  return isa<VariableArrayType>(CanonicalType.getUnqualifiedType());
+}
 inline bool Type::isRecordType() const {
   return isa<RecordType>(CanonicalType.getUnqualifiedType());
 }
 inline bool Type::isAnyComplexType() const {
-  return isa<ComplexType>(CanonicalType);
+  return isa<ComplexType>(CanonicalType.getUnqualifiedType());
 }
 inline bool Type::isVectorType() const {
   return isa<VectorType>(CanonicalType.getUnqualifiedType());
@@ -1326,13 +1318,13 @@
   return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
 }
 inline bool Type::isObjCInterfaceType() const {
-  return isa<ObjCInterfaceType>(CanonicalType);
+  return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
 }
 inline bool Type::isObjCQualifiedInterfaceType() const {
-  return isa<ObjCQualifiedInterfaceType>(CanonicalType);
+  return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
 }
 inline bool Type::isObjCQualifiedIdType() const {
-  return isa<ObjCQualifiedIdType>(CanonicalType);
+  return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
 }
 }  // end namespace clang
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug  4 02:31:14 2008
@@ -375,7 +375,7 @@
       // Flexible array members don't have any size, but they
       // have to be aligned appropriately for their element type.
       FieldSize = 0;
-      const ArrayType* ATy = FD->getType()->getAsArrayType();
+      const ArrayType* ATy = Context.getAsArrayType(FD->getType());
       FieldAlign = Context.getTypeAlign(ATy->getElementType());
     } else {
       std::pair<uint64_t, unsigned> FieldInfo = 
@@ -1018,8 +1018,107 @@
 /// for exact equality with a simple pointer comparison.
 QualType ASTContext::getCanonicalType(QualType T) {
   QualType CanType = T.getTypePtr()->getCanonicalTypeInternal();
-  return QualType(CanType.getTypePtr(),
-                  T.getCVRQualifiers() | CanType.getCVRQualifiers());
+  
+  // If the result has type qualifiers, make sure to canonicalize them as well.
+  unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers();
+  if (TypeQuals == 0) return CanType;
+
+  // If the type qualifiers are on an array type, get the canonical type of the
+  // array with the qualifiers applied to the element type.
+  ArrayType *AT = dyn_cast<ArrayType>(CanType);
+  if (!AT)
+    return CanType.getQualifiedType(TypeQuals);
+  
+  // Get the canonical version of the element with the extra qualifiers on it.
+  // This can recursively sink qualifiers through multiple levels of arrays.
+  QualType NewEltTy=AT->getElementType().getWithAdditionalQualifiers(TypeQuals);
+  NewEltTy = getCanonicalType(NewEltTy);
+  
+  if (ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+    return getConstantArrayType(NewEltTy, CAT->getSize(),CAT->getSizeModifier(),
+                                CAT->getIndexTypeQualifier());
+  if (IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT))
+    return getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
+                                  IAT->getIndexTypeQualifier());
+  
+  // FIXME: What is the ownership of size expressions in VLAs?
+  VariableArrayType *VAT = cast<VariableArrayType>(AT);
+  return getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
+                              VAT->getSizeModifier(),
+                              VAT->getIndexTypeQualifier());
+}
+
+
+const ArrayType *ASTContext::getAsArrayType(QualType T) {
+  // Handle the non-qualified case efficiently.
+  if (T.getCVRQualifiers() == 0) {
+    // Handle the common positive case fast.
+    if (const ArrayType *AT = dyn_cast<ArrayType>(T))
+      return AT;
+  }
+  
+  // Handle the common negative case fast, ignoring CVR qualifiers.
+  QualType CType = T->getCanonicalTypeInternal();
+    
+  // Make sure to look through type qualifiers (like ASQuals) for the negative
+  // test.
+  if (!isa<ArrayType>(CType) &&
+      !isa<ArrayType>(CType.getUnqualifiedType()))
+    return 0;
+  
+  // Apply any CVR qualifiers from the array type to the element type.  This
+  // implements C99 6.7.3p8: "If the specification of an array type includes
+  // any type qualifiers, the element type is so qualified, not the array type."
+  
+  // If we get here, we either have type qualifiers on the type, or we have
+  // sugar such as a typedef in the way.  If we have type qualifiers on the type
+  // we must propagate them down into the elemeng type.
+  unsigned CVRQuals = T.getCVRQualifiers();
+  unsigned AddrSpace = 0;
+  Type *Ty = T.getTypePtr();
+  
+  // Rip through ASQualType's and typedefs to get to a concrete type.
+  while (1) {
+    if (const ASQualType *ASQT = dyn_cast<ASQualType>(Ty)) {
+      AddrSpace = ASQT->getAddressSpace();
+      Ty = ASQT->getBaseType();
+    } else {
+      T = Ty->getDesugaredType();
+      if (T.getTypePtr() == Ty && T.getCVRQualifiers() == 0)
+        break;
+      CVRQuals |= T.getCVRQualifiers();
+      Ty = T.getTypePtr();
+    }
+  }
+  
+  // If we have a simple case, just return now.
+  const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
+  if (ATy == 0 || (AddrSpace == 0 && CVRQuals == 0))
+    return ATy;
+  
+  // Otherwise, we have an array and we have qualifiers on it.  Push the
+  // qualifiers into the array element type and return a new array type.
+  // Get the canonical version of the element with the extra qualifiers on it.
+  // This can recursively sink qualifiers through multiple levels of arrays.
+  QualType NewEltTy = ATy->getElementType();
+  if (AddrSpace)
+    NewEltTy = getASQualType(NewEltTy, AddrSpace);
+  NewEltTy = NewEltTy.getWithAdditionalQualifiers(CVRQuals);
+  
+  if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
+    return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
+                                                CAT->getSizeModifier(),
+                                                CAT->getIndexTypeQualifier()));
+  if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
+    return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
+                                                  IAT->getSizeModifier(),
+                                                 IAT->getIndexTypeQualifier()));
+  
+  // FIXME: What is the ownership of size expressions in VLAs?
+  const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
+  return cast<ArrayType>(getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
+                                              VAT->getSizeModifier(),
+                                              VAT->getIndexTypeQualifier()));
 }
 
 
@@ -1030,60 +1129,17 @@
 ///
 /// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
 QualType ASTContext::getArrayDecayedType(QualType Ty) {
-  // Handle the common case where typedefs are not involved directly.
-  QualType EltTy;
-  unsigned ArrayQuals = 0;
-  unsigned PointerQuals = 0;
-  if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
-    // Since T "isa" an array type, it could not have had an address space
-    // qualifier, just CVR qualifiers.  The properly qualified element pointer
-    // gets the union of the CVR qualifiers from the element and the array, and
-    // keeps any address space qualifier on the element type if present.
-    EltTy = AT->getElementType();
-    ArrayQuals = Ty.getCVRQualifiers();
-    PointerQuals = AT->getIndexTypeQualifier();
-  } else {
-    // Otherwise, we have an ASQualType or a typedef, etc.  Make sure we don't
-    // lose qualifiers when dealing with typedefs. Example:
-    //   typedef int arr[10];
-    //   void test2() {
-    //     const arr b;
-    //     b[4] = 1;
-    //   }
-    //
-    // The decayed type of b is "const int*" even though the element type of the
-    // array is "int".
-    QualType CanTy = getCanonicalType(Ty);
-    const ArrayType *PrettyArrayType = Ty->getAsArrayType();
-    assert(PrettyArrayType && "Not an array type!");
-    
-    // Get the element type with 'getAsArrayType' so that we don't lose any
-    // typedefs in the element type of the array.
-    EltTy = PrettyArrayType->getElementType();
-
-    // If the array was address-space qualifier, make sure to ASQual the element
-    // type.  We can just grab the address space from the canonical type.
-    if (unsigned AS = CanTy.getAddressSpace())
-      EltTy = getASQualType(EltTy, AS);
-    
-    // To properly handle [multiple levels of] typedefs, typeof's etc, we take
-    // the CVR qualifiers directly from the canonical type, which is guaranteed
-    // to have the full set unioned together.
-    ArrayQuals = CanTy.getCVRQualifiers();
-    PointerQuals = PrettyArrayType->getIndexTypeQualifier();
-  }
+  // Get the element type with 'getAsArrayType' so that we don't lose any
+  // typedefs in the element type of the array.  This also handles propagation
+  // of type qualifiers from the array type into the element type if present
+  // (C99 6.7.3p8).
+  const ArrayType *PrettyArrayType = getAsArrayType(Ty);
+  assert(PrettyArrayType && "Not an array type!");
   
-  // Apply any CVR qualifiers from the array type to the element type.  This
-  // implements C99 6.7.3p8: "If the specification of an array type includes
-  // any type qualifiers, the element type is so qualified, not the array type."
-  EltTy = EltTy.getQualifiedType(ArrayQuals | EltTy.getCVRQualifiers());
-
-  QualType PtrTy = getPointerType(EltTy);
+  QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
 
   // int x[restrict 4] ->  int *restrict
-  PtrTy = PtrTy.getQualifiedType(PointerQuals);
-
-  return PtrTy;
+  return PtrTy.getQualifiedType(PrettyArrayType->getIndexTypeQualifier());
 }
 
 /// getFloatingRank - Return a relative rank for floating point types.
@@ -1308,8 +1364,7 @@
 }
 
 void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
-       llvm::SmallVector<const RecordType *, 8> &ERType) const
-{
+       llvm::SmallVector<const RecordType *, 8> &ERType) const {
   // FIXME: This currently doesn't encode:
   // @ An object (whether statically typed or typed id)
   // # A class object (Class)
@@ -1372,7 +1427,9 @@
     
     S += '^';
     getObjCEncodingForType(PT->getPointeeType(), S, ERType);
-  } else if (const ArrayType *AT = T->getAsArrayType()) {
+  } else if (const ArrayType *AT =
+               // Ignore type qualifiers etc.
+               dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
     S += '[';
     
     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Aug  4 02:31:14 2008
@@ -466,14 +466,17 @@
   case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
   case LV_InvalidExpression: return MLV_InvalidExpression;
   }
-  if (TR.isConstQualified())
+  
+  QualType CT = Ctx.getCanonicalType(getType());
+  
+  if (CT.isConstQualified())
     return MLV_ConstQualified;
-  if (TR->isArrayType())
+  if (CT->isArrayType())
     return MLV_ArrayType;
-  if (TR->isIncompleteType())
+  if (CT->isIncompleteType())
     return MLV_IncompleteType;
     
-  if (const RecordType *r = TR->getAsRecordType()) {
+  if (const RecordType *r = CT->getAsRecordType()) {
     if (r->hasConstFields()) 
       return MLV_ConstQualified;
   }

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

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Aug  4 02:31:14 2008
@@ -35,6 +35,45 @@
   delete this;  
 }
 
+
+/// getArrayElementTypeNoTypeQual - If this is an array type, return the
+/// element type of the array, potentially with type qualifiers missing.
+/// This method should never be used when type qualifiers are meaningful.
+const Type *Type::getArrayElementTypeNoTypeQual() const {
+  // If this is directly an array type, return it.
+  if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
+    return ATy->getElementType().getTypePtr();
+    
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<ArrayType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (ArrayType *AT = dyn_cast<ArrayType>(CanonicalType.getUnqualifiedType()))
+      return AT->getElementType().getTypePtr();
+    return 0;
+  }
+  
+  // If this is a typedef for an array type, strip the typedef off without
+  // losing all typedef information.
+  return getDesugaredType()->getArrayElementTypeNoTypeQual();
+}
+
+/// 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.
+QualType Type::getDesugaredType() const {
+  if (const TypedefType *TDT = dyn_cast<TypedefType>(this))
+    return TDT->LookThroughTypedefs();
+  if (const TypeOfExpr *TOE = dyn_cast<TypeOfExpr>(this))
+    return TOE->getUnderlyingExpr()->getType();
+  if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
+    return TOT->getUnderlyingType();
+  // FIXME: remove this cast.
+  return QualType(const_cast<Type*>(this), 0);
+}
+
 /// isVoidType - Helper method to determine if this is the 'void' type.
 bool Type::isVoidType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
@@ -118,23 +157,6 @@
   return getDesugaredType()->getAsComplexIntegerType();
 }
 
-/// 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))
@@ -230,71 +252,17 @@
   return getDesugaredType()->getAsReferenceType();
 }
 
-const ArrayType *Type::getAsArrayType() const {
-  // If this is directly an array type, return it.
-  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)) {
-    // Look through type qualifiers
-    if (isa<ArrayType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAsArrayType();
-    return 0;
-  }
-  
-  // If this is a typedef for an array type, strip the typedef off without
-  // losing all typedef information.
-  return getDesugaredType()->getAsArrayType();
-}
-
-const ConstantArrayType *Type::getAsConstantArrayType() const {
-  // If this is directly a constant array type, return it.
-  if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
-    return ATy;
-
-  // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ConstantArrayType>(CanonicalType)) {
-    // Look through type qualifiers
-    if (isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAsConstantArrayType();
-    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 {
-  // If this is directly a variable array type, return it.
-  if (const VariableArrayType *ATy = dyn_cast<VariableArrayType>(this))
-    return ATy;
-  
-  // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<VariableArrayType>(CanonicalType)) {
-    // Look through type qualifiers
-    if (isa<VariableArrayType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAsVariableArrayType();
-    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.5p3) - Return true for variable length
 /// array types and types that contain variable array types in their
 /// declarator
 bool Type::isVariablyModifiedType() const {
-  // A VLA is a veriably modified type
-  if (getAsVariableArrayType())
+  // A VLA is a variably modified type.
+  if (isVariableArrayType())
     return true;
 
   // An array can contain a variably modified type
-  if (const ArrayType* AT = getAsArrayType())
-    return AT->getElementType()->isVariablyModifiedType();
+  if (const Type *T = getArrayElementTypeNoTypeQual())
+    return T->isVariablyModifiedType();
 
   // A pointer can point to a variably modified type
   if (const PointerType* PT = getAsPointerType())
@@ -310,28 +278,6 @@
   return false;
 }
 
-bool Type::isIncompleteArrayType() const {
-  return isa<IncompleteArrayType>(CanonicalType);
-}
-
-const IncompleteArrayType *Type::getAsIncompleteArrayType() const {
-  // If this is directly a variable array type, return it.
-  if (const IncompleteArrayType *ATy = dyn_cast<IncompleteArrayType>(this))
-    return ATy;
-  
-  // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<IncompleteArrayType>(CanonicalType)) {
-    // Look through type qualifiers
-    if (isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAsIncompleteArrayType();
-    return 0;
-  }
-
-  // If this is a typedef for a variable array type, strip the typedef off
-  // without losing all typedef information.
-  return getDesugaredType()->getAsIncompleteArrayType();
-}
-
 const RecordType *Type::getAsRecordType() const {
   // If this is directly a reference type, return it.
   if (const RecordType *RTy = dyn_cast<RecordType>(this))

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Aug  4 02:31:14 2008
@@ -108,10 +108,8 @@
   delete GlobalVariableAnchor;
 }
 
-void CGDebugInfo::setLocation(SourceLocation loc)
-{
-  SourceManager &SM = M->getContext().getSourceManager();
-  CurLoc = SM.getLogicalLoc(loc);
+void CGDebugInfo::setLocation(SourceLocation loc) {
+  CurLoc = M->getContext().getSourceManager().getLogicalLoc(loc);
 }
 
 /// getCastValueFor - Return a llvm representation for a given debug information
@@ -481,20 +479,20 @@
   // Add the dimensions of the array.
   std::vector<llvm::DebugInfoDesc *> &Elements = ArrayTy->getElements();
   do {
+    const ArrayType *AT = M->getContext().getAsArrayType(type);
     llvm::SubrangeDesc *Subrange = new llvm::SubrangeDesc();
 
     // push it back on the subrange desc list so that we can free it later.
     SubrangeDescList.push_back(Subrange);
 
     uint64_t Upper = 0;
-    if (type->getTypeClass() == Type::ConstantArray) {
-      const ConstantArrayType *ConstArrTy = type->getAsConstantArrayType();
+    if (const ConstantArrayType *ConstArrTy = dyn_cast<ConstantArrayType>(AT)) {
       Upper = ConstArrTy->getSize().getZExtValue() - 1;
     }
     Subrange->setLo(0);
     Subrange->setHi(Upper);
     Elements.push_back(Subrange);
-    type = type->getAsArrayType()->getElementType();
+    type = AT->getElementType();
   } while (type->isArrayType());
 
   ArrayTy->setFromType(getOrCreateType(type, Unit));

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Aug  4 02:31:14 2008
@@ -429,7 +429,8 @@
   std::string StringLiteral(StrData, StrData+Len);
 
   // Resize the string to the right size
-  const ConstantArrayType *CAT = E->getType()->getAsConstantArrayType();
+  const ConstantArrayType *CAT =
+    getContext().getAsConstantArrayType(E->getType());
   uint64_t RealLen = CAT->getSize().getZExtValue();
   StringLiteral.resize(RealLen, '\0');
 

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Mon Aug  4 02:31:14 2008
@@ -393,11 +393,10 @@
     }
 
     uint64_t NumArrayElements = AType->getNumElements();
-    QualType ElementType = E->getType()->getAsArrayType()->getElementType();
+    QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
+    ElementType =CGF.getContext().getAsArrayType(ElementType)->getElementType();
     
-    unsigned CVRqualifier =
-      CGF.getContext().getCanonicalType(E->getType())->getAsArrayType()
-                            ->getElementType().getCVRQualifiers();
+    unsigned CVRqualifier = ElementType.getCVRQualifiers();
 
     for (uint64_t i = 0; i != NumArrayElements; ++i) {
       llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Aug  4 02:31:14 2008
@@ -85,7 +85,7 @@
     unsigned NumInitElements = ILE->getNumInits();
     // FIXME: Check for wide strings
     if (NumInitElements > 0 && isa<StringLiteral>(ILE->getInit(0)) &&
-        ILE->getType()->getAsArrayType()->getElementType()->isCharType())
+        ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType())
       return Visit(ILE->getInit(0));
     const llvm::Type *ElemTy = AType->getElementType();
     unsigned NumElements = AType->getNumElements();
@@ -332,9 +332,7 @@
       llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
       llvm::Constant *Ops[] = {Idx0, Idx0};
       C = llvm::ConstantExpr::getGetElementPtr(C, Ops, 2);
-
-      QualType ElemType = SType->getAsArrayType()->getElementType();
-      T = CGM.getContext().getPointerType(ElemType);
+      T = CGM.getContext().getArrayDecayedType(SType);
     } else if (SType->isFunctionType()) {
       // Function types decay to a pointer to the function
       C = EmitLValue(SExpr);
@@ -357,7 +355,8 @@
     // Otherwise this must be a string initializing an array in a static
     // initializer.  Don't emit it as the address of the string, emit the string
     // data itself as an inline array.
-    const ConstantArrayType *CAT = E->getType()->getAsConstantArrayType();
+    const ConstantArrayType *CAT =
+      CGM.getContext().getAsConstantArrayType(E->getType());
     assert(CAT && "String isn't pointer or array!");
     
     std::string Str(StrData, StrData + Len);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Aug  4 02:31:14 2008
@@ -632,7 +632,8 @@
 
   // FIXME: This is silly; getTypeAlign should just work for incomplete arrays
   unsigned Align;
-  if (const IncompleteArrayType* IAT = D->getType()->getAsIncompleteArrayType())
+  if (const IncompleteArrayType* IAT =
+        Context.getAsIncompleteArrayType(D->getType()))
     Align = Context.getTypeAlign(IAT->getElementType());
   else
     Align = Context.getTypeAlign(D->getType());

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug  4 02:31:14 2008
@@ -386,8 +386,8 @@
 /// definition that would be otherwise equivalent.
 static bool areEquivalentArrayTypes(QualType NewQType, QualType OldQType,
                                     ASTContext &Context) {
-  const ArrayType *NewAT = NewQType->getAsArrayType();
-  const ArrayType *OldAT = OldQType->getAsArrayType();
+  const ArrayType *NewAT = Context.getAsArrayType(NewQType);
+  const ArrayType *OldAT = Context.getAsArrayType(OldQType);
 
   if (!NewAT || !OldAT)
     return false;
@@ -549,7 +549,9 @@
 }
 
 bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
-  if (const IncompleteArrayType *IAT = DeclT->getAsIncompleteArrayType()) {
+  const ArrayType *AT = Context.getAsArrayType(DeclT);
+  
+  if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
     // C99 6.7.8p14. We have an array of character type with unknown size 
     // being initialized to a string literal.
     llvm::APSInt ConstVal(32);
@@ -557,14 +559,14 @@
     // Return a new array type (C99 6.7.8p22).
     DeclT = Context.getConstantArrayType(IAT->getElementType(), ConstVal, 
                                          ArrayType::Normal, 0);
-  } else if (const ConstantArrayType *CAT = DeclT->getAsConstantArrayType()) {
+  } else {
+    const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
     // C99 6.7.8p14. We have an array of character type with known size.
-    if (strLiteral->getByteLength() > (unsigned)CAT->getMaximumElements())
+    // FIXME: Avoid truncation for 64-bit length strings.
+    if (strLiteral->getByteLength() > (unsigned)CAT->getSize().getZExtValue())
       Diag(strLiteral->getSourceRange().getBegin(),
            diag::warn_initializer_string_for_char_array_too_long,
            strLiteral->getSourceRange());
-  } else {
-    assert(0 && "HandleStringLiteralInit(): Invalid array type");
   }
   // Set type from "char *" to "constant array of char".
   strLiteral->setType(DeclT);
@@ -573,7 +575,7 @@
 }
 
 StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) {
-  const ArrayType *AT = DeclType->getAsArrayType();
+  const ArrayType *AT = Context.getAsArrayType(DeclType);
   if (AT && AT->getElementType()->isCharType()) {
     return dyn_cast<StringLiteral>(Init);
   }
@@ -583,7 +585,7 @@
 bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {  
   // C99 6.7.8p3: The type of the entity to be initialized shall be an array
   // of unknown size ("[]") or an object type that is not a variable array type.
-  if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType())
+  if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
     return Diag(VAT->getSizeExpr()->getLocStart(), 
                 diag::err_variable_object_no_init, 
                 VAT->getSizeExpr()->getSourceRange());
@@ -1393,7 +1395,7 @@
     // static storage duration, it shall not have a variable length array.
     if ((IDecl->isFileVarDecl() || IDecl->isBlockVarDecl()) && 
         IDecl->getStorageClass() == VarDecl::Static) {
-      if (T->getAsVariableArrayType()) {
+      if (T->isVariableArrayType()) {
         Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla);
         IDecl->setInvalidDecl();
       }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug  4 02:31:14 2008
@@ -1055,7 +1055,7 @@
   Expr *literalExpr = static_cast<Expr*>(InitExpr);
 
   if (literalType->isArrayType()) {
-    if (literalType->getAsVariableArrayType())
+    if (literalType->isVariableArrayType())
       return Diag(LParenLoc,
                   diag::err_variable_object_no_init,
                   SourceRange(LParenLoc,
@@ -2381,7 +2381,7 @@
     const OffsetOfComponent &OC = CompPtr[i];
     if (OC.isBrackets) {
       // Offset of an array sub-field.  TODO: Should we allow vector elements?
-      const ArrayType *AT = Res->getType()->getAsArrayType();
+      const ArrayType *AT = Context.getAsArrayType(Res->getType());
       if (!AT) {
         delete Res;
         return Diag(OC.LocEnd, diag::err_offsetof_array_type,

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Aug  4 02:31:14 2008
@@ -30,7 +30,8 @@
 int InitListChecker::numArrayElements(QualType DeclType) {
   // FIXME: use a proper constant
   int maxElements = 0x7FFFFFFF;
-  if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
+  if (const ConstantArrayType *CAT =
+        SemaRef->Context.getAsConstantArrayType(DeclType)) {
     maxElements = static_cast<int>(CAT->getSize().getZExtValue());
   }
   return maxElements;
@@ -231,7 +232,8 @@
       return;
     }
   }
-  if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) {
+  if (const VariableArrayType *VAT =
+        SemaRef->Context.getAsVariableArrayType(DeclType)) {
     // Check for VLAs; in standard C it would be possible to check this
     // earlier, but I don't know where clang accepts VLAs (gcc accepts
     // them in all sorts of strange places).
@@ -243,7 +245,8 @@
   }
 
   int maxElements = numArrayElements(DeclType);
-  QualType elementType = DeclType->getAsArrayType()->getElementType();
+  QualType elementType = SemaRef->Context.getAsArrayType(DeclType)
+                             ->getElementType();
   int numElements = 0;
   for (int i = 0; i < maxElements; ++i, ++numElements) {
     // Don't attempt to go past the end of the init list

Modified: cfe/trunk/test/Sema/typedef-retain.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/typedef-retain.c?rev=54317&r1=54316&r2=54317&view=diff

==============================================================================
--- cfe/trunk/test/Sema/typedef-retain.c (original)
+++ cfe/trunk/test/Sema/typedef-retain.c Mon Aug  4 02:31:14 2008
@@ -14,13 +14,25 @@
 
 // PR2039
 typedef int a[5];
-void z() {
+void test3() {
   typedef const a b;
   b r;
   r[0]=10;  // expected-error {{read-only variable is not assignable}}
 }
 
-int e(const a y) {
+int test4(const a y) {
   y[0] = 10; // expected-error {{read-only variable is not assignable}}
 }
 
+// PR2189
+int test5() {
+  const int s[5]; int t[5]; 
+  return &s == &t;   // expected-warning {{comparison of distinct pointer types}}
+}
+
+int test6() {
+  const a s; 
+  a t; 
+  return &s == &t;   // expected-warning {{comparison of distinct pointer types}}
+}
+





More information about the cfe-commits mailing list