[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