diff options
author | Chris Lattner <sabre@nondot.org> | 2008-08-04 07:31:14 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-08-04 07:31:14 +0000 |
commit | 7adf07608847865d47fa50640c3b18007953c4aa (patch) | |
tree | 263f2ca4985a4e008e230fee9d2e6c4794075625 /clang/lib | |
parent | a01ede2f1105780926d58af04d0e4db09140221f (diff) | |
download | bcm5719-llvm-7adf07608847865d47fa50640c3b18007953c4aa.tar.gz bcm5719-llvm-7adf07608847865d47fa50640c3b18007953c4aa.zip |
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.
llvm-svn: 54317
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 171 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 11 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 140 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 9 |
11 files changed, 200 insertions, 191 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 47a3e3ac67f..002a51f877a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -375,7 +375,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo, // 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 @@ QualType ASTContext::getPointerDiffType() const { /// 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 @@ QualType ASTContext::getCanonicalType(QualType T) { /// /// 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::getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl, } 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 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, 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)) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 60b762f66d6..21f2b07d132 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -466,14 +466,17 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const { 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; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index d32f963acb1..f9f6ecac071 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -35,6 +35,45 @@ void VariableArrayType::Destroy(ASTContext& C) { 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 @@ const ComplexType *Type::getAsComplexIntegerType() const { 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 @@ const ReferenceType *Type::getAsReferenceType() const { 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 @@ bool Type::isVariablyModifiedType() const { 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)) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d232fd95601..0b63463d1f7 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -108,10 +108,8 @@ CGDebugInfo::~CGDebugInfo() 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 @@ CGDebugInfo::getOrCreateArrayType(QualType type, llvm::CompileUnitDesc *Unit) // 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)); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1fd616c6488..ca52b070dd1 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -429,7 +429,8 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { 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'); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 815e296e79b..df90ee09f5c 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -393,11 +393,10 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { } 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"); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 681993a5d4a..d58d0046072 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -85,7 +85,7 @@ public: 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 @@ public: 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 @@ public: // 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); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b531616b13c..5d85b7a70f4 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -632,7 +632,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // 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()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f8835ffa8cb..e9343e39899 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -386,8 +386,8 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { /// 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::CheckSingleInitializer(Expr *&Init, QualType DeclType) { } 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 @@ bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) { // 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 @@ bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) { } 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 @@ StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) { 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 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) { // 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(); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 56632d1d772..6c6d6e2610a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1055,7 +1055,7 @@ ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, 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 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc, 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, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 0078cc149cd..1889bafacb0 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -30,7 +30,8 @@ InitListChecker::InitListChecker(Sema *S, InitListExpr *IL, QualType &T) { 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 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, 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 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, } 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 |