From: John McCall Date: Tue, 18 Jan 2011 08:40:38 +0000 (+0000) Subject: Fix some unnecessarily complicated code for canonicalizing variably-modified X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ce8890371fcdb983ae487c87fa40606a34896ff7;p=clang Fix some unnecessarily complicated code for canonicalizing variably-modified parameter types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123753 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 9d9147e546..58a69dc235 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -594,12 +594,8 @@ public: ArrayType::ArraySizeModifier ASM, unsigned EltTypeQuals) const; - /// getUnknownSizeVariableArrayType - Return a variable array type with - /// all variable indices replaced with unknow [*] size. - QualType getUnknownSizeVariableArrayType(QualType Ty) const; - /// getVariableArrayDecayedType - Returns a vla type where known sizes - /// are replaced with [*] + /// are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; /// getVectorType - Return the unique reference to a vector type of diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index ec9de25017..dc484c8806 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1414,53 +1414,129 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, return QualType(New, 0); } -/// getIncompleteArrayType - Returns a unique reference to the type for a -/// incomplete array of the specified element type. -QualType ASTContext::getUnknownSizeVariableArrayType(QualType Ty) const { - QualType ElemTy = getBaseElementType(Ty); - DeclarationName Name; - llvm::SmallVector ATypes; - QualType ATy = Ty; - while (const ArrayType *AT = getAsArrayType(ATy)) { - ATypes.push_back(ATy); - ATy = AT->getElementType(); - } - for (int i = ATypes.size() - 1; i >= 0; i--) { - if (const VariableArrayType *VAT = getAsVariableArrayType(ATypes[i])) { - ElemTy = getVariableArrayType(ElemTy, /*ArraySize*/0, ArrayType::Star, - 0, VAT->getBracketsRange()); - } - else if (const ConstantArrayType *CAT = getAsConstantArrayType(ATypes[i])) { - llvm::APSInt ConstVal(CAT->getSize()); - ElemTy = getConstantArrayType(ElemTy, ConstVal, ArrayType::Normal, 0); - } - else if (getAsIncompleteArrayType(ATypes[i])) { - ElemTy = getVariableArrayType(ElemTy, /*ArraySize*/0, ArrayType::Normal, - 0, SourceRange()); - } - else - assert(false && "DependentArrayType is seen"); +/// getVariableArrayDecayedType - Turns the given type, which may be +/// variably-modified, into the corresponding type with all the known +/// sizes replaced with [*]. +QualType ASTContext::getVariableArrayDecayedType(QualType type) const { + // Vastly most common case. + if (!type->isVariablyModifiedType()) return type; + + QualType result; + + SplitQualType split = type.getSplitDesugaredType(); + const Type *ty = split.first; + switch (ty->getTypeClass()) { +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("didn't desugar past all non-canonical types?"); + + // These types should never be variably-modified. + case Type::Builtin: + case Type::Complex: + case Type::Vector: + case Type::ExtVector: + case Type::DependentSizedExtVector: + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Record: + case Type::Enum: + case Type::UnresolvedUsing: + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::Decltype: + case Type::DependentName: + case Type::InjectedClassName: + case Type::TemplateSpecialization: + case Type::DependentTemplateSpecialization: + case Type::TemplateTypeParm: + case Type::SubstTemplateTypeParmPack: + case Type::PackExpansion: + llvm_unreachable("type should never be variably-modified"); + + // These types can be variably-modified but should never need to + // further decay. + case Type::FunctionNoProto: + case Type::FunctionProto: + case Type::BlockPointer: + case Type::MemberPointer: + return type; + + // These types can be variably-modified. All these modifications + // preserve structure except as noted by comments. + // TODO: if we ever care about optimizing VLAs, there are no-op + // optimizations available here. + case Type::Pointer: + result = getPointerType(getVariableArrayDecayedType( + cast(ty)->getPointeeType())); + break; + + case Type::LValueReference: { + const LValueReferenceType *lv = cast(ty); + result = getLValueReferenceType( + getVariableArrayDecayedType(lv->getPointeeType()), + lv->isSpelledAsLValue()); + break; } - return ElemTy; -} -/// getVariableArrayDecayedType - Returns a vla type where known sizes -/// are replaced with [*] -QualType ASTContext::getVariableArrayDecayedType(QualType Ty) const { - if (Ty->isPointerType()) { - QualType BaseType = Ty->getAs()->getPointeeType(); - if (isa(BaseType)) { - ArrayType *AT = dyn_cast(BaseType); - VariableArrayType *VAT = cast(AT); - if (VAT->getSizeExpr()) { - Ty = getUnknownSizeVariableArrayType(BaseType); - Ty = getPointerType(Ty); - } - } + case Type::RValueReference: { + const RValueReferenceType *lv = cast(ty); + result = getRValueReferenceType( + getVariableArrayDecayedType(lv->getPointeeType())); + break; + } + + case Type::ConstantArray: { + const ConstantArrayType *cat = cast(ty); + result = getConstantArrayType( + getVariableArrayDecayedType(cat->getElementType()), + cat->getSize(), + cat->getSizeModifier(), + cat->getIndexTypeCVRQualifiers()); + break; } - return Ty; -} + case Type::DependentSizedArray: { + const DependentSizedArrayType *dat = cast(ty); + result = getDependentSizedArrayType( + getVariableArrayDecayedType(dat->getElementType()), + dat->getSizeExpr(), + dat->getSizeModifier(), + dat->getIndexTypeCVRQualifiers(), + dat->getBracketsRange()); + break; + } + + // Turn incomplete types into [*] types. + case Type::IncompleteArray: { + const IncompleteArrayType *iat = cast(ty); + result = getVariableArrayType( + getVariableArrayDecayedType(iat->getElementType()), + /*size*/ 0, + ArrayType::Normal, + iat->getIndexTypeCVRQualifiers(), + SourceRange()); + break; + } + + // Turn VLA types into [*] types. + case Type::VariableArray: { + const VariableArrayType *vat = cast(ty); + result = getVariableArrayType( + getVariableArrayDecayedType(vat->getElementType()), + /*size*/ 0, + ArrayType::Star, + vat->getIndexTypeCVRQualifiers(), + vat->getBracketsRange()); + break; + } + } + + // Apply the top-level qualifiers from the original. + return getQualifiedType(result, split.second); +} /// getVariableArrayType - Returns a non-unique reference to the type for a /// variable array of the specified element type.