From: Douglas Gregor Date: Mon, 6 Jul 2009 15:59:29 +0000 (+0000) Subject: Keep track of the Expr used to describe the size of an array type, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7e7eb3da052a6d80ddf2377cab0384c798f73f75;p=clang Keep track of the Expr used to describe the size of an array type, from Enea Zaffanella! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74831 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 041a0f33ad..e85eac59a7 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -274,7 +274,8 @@ public: /// variable array of the specified element type. QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals); + unsigned EltTypeQuals, + SourceRange Brackets); /// getDependentSizedArrayType - Returns a non-unique reference to /// the type for a dependently-sized array of the specified element @@ -282,7 +283,8 @@ public: /// comparable, at some point. QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals); + unsigned EltTypeQuals, + SourceRange Brackets); /// getIncompleteArrayType - Returns a unique reference to the type for a /// incomplete array of the specified element type. @@ -295,7 +297,23 @@ public: QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned EltTypeQuals); - + + /// getConstantArrayWithExprType - Return a reference to the type for a + /// constant array of the specified element type. + QualType getConstantArrayWithExprType(QualType EltTy, + const llvm::APInt &ArySize, + Expr *ArySizeExpr, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals, + SourceRange Brackets); + + /// getConstantArrayWithoutExprType - Return a reference to the type + /// for a constant array of the specified element type. + QualType getConstantArrayWithoutExprType(QualType EltTy, + const llvm::APInt &ArySize, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals); + /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts); diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 6ad3a6bcc2..a054522423 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -79,6 +79,24 @@ struct PrintingPolicy { /// and pretty-printing involves printing something similar to /// source code. bool Dump : 1; + + /// \brief Whether we should print the sizes of constant array expressions + /// as written in the sources. + /// + /// This flag is determines whether arrays types declared as + /// + /// \code + /// int a[4+10*10]; + /// char a[] = "A string"; + /// \endcode + /// + /// will be printed as written or as follows: + /// + /// \code + /// int a[104]; + /// char a[9] = "A string"; + /// \endcode + bool ConstantArraySizeAsWritten : 1; }; } // end namespace clang diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index a00c0c4ff1..ffba78a3c8 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -291,7 +291,7 @@ private: /// TypeClass bitfield - Enum that specifies what subclass this belongs to. /// Note that this should stay at the end of the ivars for Type so that /// subclasses can pack their bitfields into the same word. - unsigned TC : 5; + unsigned TC : 6; Type(const Type&); // DO NOT IMPLEMENT. void operator=(const Type&); // DO NOT IMPLEMENT. @@ -839,6 +839,8 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray || + T->getTypeClass() == ConstantArrayWithExpr || + T->getTypeClass() == ConstantArrayWithoutExpr || T->getTypeClass() == VariableArray || T->getTypeClass() == IncompleteArray || T->getTypeClass() == DependentSizedArray; @@ -846,15 +848,21 @@ public: static bool classof(const ArrayType *) { return true; } }; -/// ConstantArrayType - This class represents C arrays with a specified constant -/// size. For example 'int A[100]' has ConstantArrayType where the element type -/// is 'int' and the size is 100. +/// ConstantArrayType - This class represents the canonical version of +/// C arrays with a specified constant size. For example, the canonical +/// type for 'int A[4 + 4*100]' is a ConstantArrayType where the element +/// type is 'int' and the size is 404. class ConstantArrayType : public ArrayType { llvm::APInt Size; // Allows us to unique the type. ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq), Size(size) {} + : ArrayType(ConstantArray, et, can, sm, tq), + Size(size) {} +protected: + ConstantArrayType(TypeClass tc, QualType et, QualType can, + const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) + : ArrayType(tc, et, can, sm, tq), Size(size) {} friend class ASTContext; // ASTContext creates these. public: const llvm::APInt &getSize() const { return Size; } @@ -872,22 +880,91 @@ public: ID.AddInteger(SizeMod); ID.AddInteger(TypeQuals); } - static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArray; + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArray || + T->getTypeClass() == ConstantArrayWithExpr || + T->getTypeClass() == ConstantArrayWithoutExpr; } static bool classof(const ConstantArrayType *) { return true; } }; +/// ConstantArrayWithExprType - This class represents C arrays with a +/// constant size specified by means of an integer constant expression. +/// For example 'int A[sizeof(int)]' has ConstantArrayWithExprType where +/// the element type is 'int' and the size expression is 'sizeof(int)'. +/// These types are non-canonical. +class ConstantArrayWithExprType : public ConstantArrayType { + /// SizeExpr - The ICE occurring in the concrete syntax. + Expr *SizeExpr; + /// Brackets - The left and right array brackets. + SourceRange Brackets; + + ConstantArrayWithExprType(QualType et, QualType can, + const llvm::APInt &size, Expr *e, + ArraySizeModifier sm, unsigned tq, + SourceRange brackets) + : ConstantArrayType(ConstantArrayWithExpr, et, can, size, sm, tq), + SizeExpr(e), Brackets(brackets) {} + friend class ASTContext; // ASTContext creates these. + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } + SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } + SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } + + virtual void getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArrayWithExpr; + } + static bool classof(const ConstantArrayWithExprType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + assert(0 && "Cannot unique ConstantArrayWithExprTypes."); + } +}; + +/// ConstantArrayWithoutExprType - This class represents C arrays with a +/// constant size that was not specified by an integer constant expression, +/// but inferred by static semantics. +/// For example 'int A[] = { 0, 1, 2 }' has ConstantArrayWithoutExprType. +/// These types are non-canonical: the corresponding canonical type, +/// having the size specified in an APInt object, is a ConstantArrayType. +class ConstantArrayWithoutExprType : public ConstantArrayType { + + ConstantArrayWithoutExprType(QualType et, QualType can, + const llvm::APInt &size, + ArraySizeModifier sm, unsigned tq) + : ConstantArrayType(ConstantArrayWithoutExpr, et, can, size, sm, tq) {} + friend class ASTContext; // ASTContext creates these. + +public: + virtual void getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantArrayWithoutExpr; + } + static bool classof(const ConstantArrayWithoutExprType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + assert(0 && "Cannot unique ConstantArrayWithoutExprTypes."); + } +}; + /// IncompleteArrayType - This class represents C arrays with an unspecified /// size. For example 'int A[]' has an IncompleteArrayType where the element /// type is 'int' and the size is unspecified. class IncompleteArrayType : public ArrayType { + IncompleteArrayType(QualType et, QualType can, - ArraySizeModifier sm, unsigned tq) + ArraySizeModifier sm, unsigned tq) : ArrayType(IncompleteArray, et, can, sm, tq) {} friend class ASTContext; // ASTContext creates these. public: - virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; static bool classof(const Type *T) { @@ -928,10 +1005,14 @@ class VariableArrayType : public ArrayType { /// SizeExpr - An assignment expression. VLA's are only permitted within /// a function block. Stmt *SizeExpr; - + /// Brackets - The left and right array brackets. + SourceRange Brackets; + VariableArrayType(QualType et, QualType can, Expr *e, - ArraySizeModifier sm, unsigned tq) - : ArrayType(VariableArray, et, can, sm, tq), SizeExpr((Stmt*) e) {} + ArraySizeModifier sm, unsigned tq, + SourceRange brackets) + : ArrayType(VariableArray, et, can, sm, tq), + SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. virtual void Destroy(ASTContext& C); @@ -941,6 +1022,9 @@ public: // to have a dependency of Type.h on Stmt.h/Expr.h. return (Expr*) SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } + SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } + SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; @@ -971,10 +1055,14 @@ class DependentSizedArrayType : public ArrayType { /// SizeExpr - An assignment expression that will instantiate to the /// size of the array. Stmt *SizeExpr; + /// Brackets - The left and right array brackets. + SourceRange Brackets; DependentSizedArrayType(QualType et, QualType can, Expr *e, - ArraySizeModifier sm, unsigned tq) - : ArrayType(DependentSizedArray, et, can, sm, tq), SizeExpr((Stmt*) e) {} + ArraySizeModifier sm, unsigned tq, + SourceRange brackets) + : ArrayType(DependentSizedArray, et, can, sm, tq), + SizeExpr((Stmt*) e), Brackets(brackets) {} friend class ASTContext; // ASTContext creates these. virtual void Destroy(ASTContext& C); @@ -984,6 +1072,9 @@ public: // to have a dependency of Type.h on Stmt.h/Expr.h. return (Expr*) SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } + SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } + SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 64a09d8002..36bc64b87b 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -57,6 +57,8 @@ TYPE(RValueReference, ReferenceType) TYPE(MemberPointer, Type) ABSTRACT_TYPE(Array, Type) TYPE(ConstantArray, ArrayType) +NON_CANONICAL_TYPE(ConstantArrayWithExpr, ConstantArrayType) +NON_CANONICAL_TYPE(ConstantArrayWithoutExpr, ConstantArrayType) TYPE(IncompleteArray, ArrayType) TYPE(VariableArray, ArrayType) DEPENDENT_TYPE(DependentSizedArray, ArrayType) diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 80aa248a78..8efaf26cc8 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -393,7 +393,11 @@ namespace clang { /// \brief An ObjCObjectPointerType record. TYPE_OBJC_OBJECT_POINTER = 23, /// \brief a DecltypeType record. - TYPE_DECLTYPE = 24 + TYPE_DECLTYPE = 24, + /// \brief A ConstantArrayWithExprType record. + TYPE_CONSTANT_ARRAY_WITH_EXPR = 25, + /// \brief A ConstantArrayWithoutExprType record. + TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 26 }; /// \brief The type IDs for special types constructed by semantic diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 300602e514..0c57915298 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -457,6 +457,8 @@ struct DeclaratorChunk { /// Loc - The place where this type was defined. SourceLocation Loc; + /// EndLoc - If valid, the place where this chunck ends. + SourceLocation EndLoc; struct PointerTypeInfo { /// The type qualifiers: const/volatile/restrict. @@ -696,10 +698,11 @@ struct DeclaratorChunk { /// static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, bool isStar, void *NumElts, - SourceLocation Loc) { + SourceLocation LBLoc, SourceLocation RBLoc) { DeclaratorChunk I; I.Kind = Array; - I.Loc = Loc; + I.Loc = LBLoc; + I.EndLoc = RBLoc; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 0075815300..08607d5ed2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -475,6 +475,8 @@ ASTContext::getTypeInfo(const Type *T) { Align = getTypeAlign(cast(T)->getElementType()); break; + case Type::ConstantArrayWithExpr: + case Type::ConstantArrayWithoutExpr: case Type::ConstantArray: { const ConstantArrayType *CAT = cast(T); @@ -1344,16 +1346,68 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, return QualType(New, 0); } +/// getConstantArrayWithExprType - Return a reference to the type for +/// an array of the specified element type. +QualType +ASTContext::getConstantArrayWithExprType(QualType EltTy, + const llvm::APInt &ArySizeIn, + Expr *ArySizeExpr, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals, + SourceRange Brackets) { + // Convert the array size into a canonical width matching the pointer + // size for the target. + llvm::APInt ArySize(ArySizeIn); + ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); + + // Compute the canonical ConstantArrayType. + QualType Canonical = getConstantArrayType(getCanonicalType(EltTy), + ArySize, ASM, EltTypeQuals); + // Since we don't unique expressions, it isn't possible to unique VLA's + // that have an expression provided for their size. + ConstantArrayWithExprType *New = + new(*this,8)ConstantArrayWithExprType(EltTy, Canonical, + ArySize, ArySizeExpr, + ASM, EltTypeQuals, Brackets); + Types.push_back(New); + return QualType(New, 0); +} + +/// getConstantArrayWithoutExprType - Return a reference to the type for +/// an array of the specified element type. +QualType +ASTContext::getConstantArrayWithoutExprType(QualType EltTy, + const llvm::APInt &ArySizeIn, + ArrayType::ArraySizeModifier ASM, + unsigned EltTypeQuals) { + // Convert the array size into a canonical width matching the pointer + // size for the target. + llvm::APInt ArySize(ArySizeIn); + ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); + + // Compute the canonical ConstantArrayType. + QualType Canonical = getConstantArrayType(getCanonicalType(EltTy), + ArySize, ASM, EltTypeQuals); + ConstantArrayWithoutExprType *New = + new(*this,8)ConstantArrayWithoutExprType(EltTy, Canonical, + ArySize, ASM, EltTypeQuals); + Types.push_back(New); + return QualType(New, 0); +} + /// getVariableArrayType - Returns a non-unique reference to the type for a /// variable array of the specified element type. -QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts, +QualType ASTContext::getVariableArrayType(QualType EltTy, + Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals) { + unsigned EltTypeQuals, + SourceRange Brackets) { // Since we don't unique expressions, it isn't possible to unique VLA's // that have an expression provided for their size. VariableArrayType *New = - new(*this,8)VariableArrayType(EltTy,QualType(), NumElts, ASM, EltTypeQuals); + new(*this,8)VariableArrayType(EltTy, QualType(), + NumElts, ASM, EltTypeQuals, Brackets); VariableArrayTypes.push_back(New); Types.push_back(New); @@ -1364,9 +1418,11 @@ QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts, /// the type for a dependently-sized array of the specified element /// type. FIXME: We will need these to be uniqued, or at least /// comparable, at some point. -QualType ASTContext::getDependentSizedArrayType(QualType EltTy, Expr *NumElts, +QualType ASTContext::getDependentSizedArrayType(QualType EltTy, + Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals) { + unsigned EltTypeQuals, + SourceRange Brackets) { assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) && "Size must be type- or value-dependent!"); @@ -1374,8 +1430,9 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy, Expr *NumElts, // dependently-sized array types. DependentSizedArrayType *New = - new (*this,8) DependentSizedArrayType(EltTy, QualType(), NumElts, - ASM, EltTypeQuals); + new (*this,8) DependentSizedArrayType(EltTy, QualType(), + NumElts, ASM, EltTypeQuals, + Brackets); DependentSizedArrayTypes.push_back(New); Types.push_back(New); @@ -1407,8 +1464,9 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy, assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; } - IncompleteArrayType *New = new (*this,8) IncompleteArrayType(EltTy, Canonical, - ASM, EltTypeQuals); + IncompleteArrayType *New + = new (*this,8) IncompleteArrayType(EltTy, Canonical, + ASM, EltTypeQuals); IncompleteArrayTypes.InsertNode(New, InsertPos); Types.push_back(New); @@ -1974,14 +2032,18 @@ QualType ASTContext::getCanonicalType(QualType T) { IAT->getIndexTypeQualifier()); if (DependentSizedArrayType *DSAT = dyn_cast(AT)) - return getDependentSizedArrayType(NewEltTy, DSAT->getSizeExpr(), + return getDependentSizedArrayType(NewEltTy, + DSAT->getSizeExpr(), DSAT->getSizeModifier(), - DSAT->getIndexTypeQualifier()); + DSAT->getIndexTypeQualifier(), + DSAT->getBracketsRange()); VariableArrayType *VAT = cast(AT); - return getVariableArrayType(NewEltTy, VAT->getSizeExpr(), + return getVariableArrayType(NewEltTy, + VAT->getSizeExpr(), VAT->getSizeModifier(), - VAT->getIndexTypeQualifier()); + VAT->getIndexTypeQualifier(), + VAT->getBracketsRange()); } Decl *ASTContext::getCanonicalDecl(Decl *D) { @@ -2136,7 +2198,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { if (const IncompleteArrayType *IAT = dyn_cast(ATy)) return cast(getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(), - IAT->getIndexTypeQualifier())); + IAT->getIndexTypeQualifier())); if (const DependentSizedArrayType *DSAT = dyn_cast(ATy)) @@ -2144,12 +2206,15 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { getDependentSizedArrayType(NewEltTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(), - DSAT->getIndexTypeQualifier())); + DSAT->getIndexTypeQualifier(), + DSAT->getBracketsRange())); const VariableArrayType *VAT = cast(ATy); - return cast(getVariableArrayType(NewEltTy, VAT->getSizeExpr(), + return cast(getVariableArrayType(NewEltTy, + VAT->getSizeExpr(), VAT->getSizeModifier(), - VAT->getIndexTypeQualifier())); + VAT->getIndexTypeQualifier(), + VAT->getBracketsRange())); } @@ -3528,7 +3593,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { } if (getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS; if (getCanonicalType(RHSElem) == getCanonicalType(ResultType)) return RHS; - return getIncompleteArrayType(ResultType, ArrayType::ArraySizeModifier(),0); + return getIncompleteArrayType(ResultType, + ArrayType::ArraySizeModifier(), 0); } case Type::FunctionNoProto: return mergeFunctionTypes(LHS, RHS); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 4e061a9fbe..2b307c86e3 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -37,6 +37,18 @@ void Type::Destroy(ASTContext& C) { C.Deallocate(this); } +void ConstantArrayWithExprType::Destroy(ASTContext& C) { + // FIXME: destruction of SizeExpr commented out due to resource contention. + // SizeExpr->Destroy(C); + // See FIXME in SemaDecl.cpp:1536: if we were able to either steal + // or clone the SizeExpr there, then here we could freely delete it. + // Since we do not know how to steal or clone, we keep a pointer to + // a shared resource, but we cannot free it. + // (There probably is a trivial solution ... for people knowing clang!). + this->~ConstantArrayWithExprType(); + C.Deallocate(this); +} + void VariableArrayType::Destroy(ASTContext& C) { if (SizeExpr) SizeExpr->Destroy(C); @@ -163,6 +175,8 @@ bool Type::isDerivedType() const { case Pointer: case VariableArray: case ConstantArray: + case ConstantArrayWithExpr: + case ConstantArrayWithoutExpr: case IncompleteArray: case FunctionProto: case FunctionNoProto: @@ -1339,6 +1353,29 @@ void ConstantArrayType::getAsStringInternal(std::string &S, const PrintingPolicy getElementType().getAsStringInternal(S, Policy); } +void ConstantArrayWithExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { + if (Policy.ConstantArraySizeAsWritten) { + std::string SStr; + llvm::raw_string_ostream s(SStr); + getSizeExpr()->printPretty(s, 0, Policy); + S += '['; + S += s.str(); + S += ']'; + getElementType().getAsStringInternal(S, Policy); + } + else + ConstantArrayType::getAsStringInternal(S, Policy); +} + +void ConstantArrayWithoutExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { + if (Policy.ConstantArraySizeAsWritten) { + S += "[]"; + getElementType().getAsStringInternal(S, Policy); + } + else + ConstantArrayType::getAsStringInternal(S, Policy); +} + void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { S += "[]"; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 2bf8a222a2..cf8e19af32 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -780,6 +780,8 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, return Slot = CreateType(cast(Ty), Unit); case Type::ConstantArray: + case Type::ConstantArrayWithExpr: + case Type::ConstantArrayWithoutExpr: case Type::VariableArray: case Type::IncompleteArray: return Slot = CreateType(cast(Ty), Unit); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 95b166159e..7d65c4b658 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1753,7 +1753,32 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { unsigned IndexTypeQuals = Record[2]; unsigned Idx = 3; llvm::APInt Size = ReadAPInt(Record, Idx); - return Context->getConstantArrayType(ElementType, Size, ASM,IndexTypeQuals); + return Context->getConstantArrayType(ElementType, Size, + ASM, IndexTypeQuals); + } + + case pch::TYPE_CONSTANT_ARRAY_WITH_EXPR: { + QualType ElementType = GetType(Record[0]); + ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; + unsigned IndexTypeQuals = Record[2]; + SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); + SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); + unsigned Idx = 5; + llvm::APInt Size = ReadAPInt(Record, Idx); + return Context->getConstantArrayWithExprType(ElementType, + Size, ReadTypeExpr(), + ASM, IndexTypeQuals, + SourceRange(LBLoc, RBLoc)); + } + + case pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR: { + QualType ElementType = GetType(Record[0]); + ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; + unsigned IndexTypeQuals = Record[2]; + unsigned Idx = 3; + llvm::APInt Size = ReadAPInt(Record, Idx); + return Context->getConstantArrayWithoutExprType(ElementType, Size, + ASM, IndexTypeQuals); } case pch::TYPE_INCOMPLETE_ARRAY: { @@ -1767,8 +1792,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType ElementType = GetType(Record[0]); ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; unsigned IndexTypeQuals = Record[2]; + SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); + SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); return Context->getVariableArrayType(ElementType, ReadTypeExpr(), - ASM, IndexTypeQuals); + ASM, IndexTypeQuals, + SourceRange(LBLoc, RBLoc)); } case pch::TYPE_VECTOR: { diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 3bfc9e89d1..fee2137314 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -124,6 +124,23 @@ void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { Code = pch::TYPE_CONSTANT_ARRAY; } +void PCHTypeWriter +::VisitConstantArrayWithExprType(const ConstantArrayWithExprType *T) { + VisitArrayType(T); + Writer.AddSourceLocation(T->getLBracketLoc(), Record); + Writer.AddSourceLocation(T->getRBracketLoc(), Record); + Writer.AddAPInt(T->getSize(), Record); + Writer.AddStmt(T->getSizeExpr()); + Code = pch::TYPE_CONSTANT_ARRAY_WITH_EXPR; +} + +void PCHTypeWriter +::VisitConstantArrayWithoutExprType(const ConstantArrayWithoutExprType *T) { + VisitArrayType(T); + Writer.AddAPInt(T->getSize(), Record); + Code = pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR; +} + void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { VisitArrayType(T); Code = pch::TYPE_INCOMPLETE_ARRAY; @@ -131,6 +148,8 @@ void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { VisitArrayType(T); + Writer.AddSourceLocation(T->getLBracketLoc(), Record); + Writer.AddSourceLocation(T->getRBracketLoc(), Record); Writer.AddStmt(T->getSizeExpr()); Code = pch::TYPE_VARIABLE_ARRAY; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4a3532c410..d599438644 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2690,7 +2690,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); // Remember that we parsed the empty array type. OwningExprResult NumElements(Actions); - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, StartLoc), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, + StartLoc, EndLoc), EndLoc); return; } else if (Tok.getKind() == tok::numeric_constant && @@ -2706,8 +2707,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { ExprRes.release(); // Deallocate expr, just use []. // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, - ExprRes.release(), StartLoc), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(), + StartLoc, EndLoc), EndLoc); return; } @@ -2770,7 +2771,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), isStar, - NumElements.release(), StartLoc), + NumElements.release(), + StartLoc, EndLoc), EndLoc); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 1220b2d27b..1c00a8eabe 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -966,7 +966,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.release(), LLoc), + Size.release(), LLoc, RLoc), RLoc); if (RLoc.isInvalid()) diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index d1e8e2104d..6cbb1c3712 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -282,8 +282,8 @@ void Sema::ActOnEndOfTranslationUnit() { llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); QualType T - = Context.getConstantArrayType(ArrayT->getElementType(), - One, ArrayType::Normal, 0); + = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(), + One, ArrayType::Normal, 0); VD->setType(T); } } else if (RequireCompleteType(VD->getLocation(), VD->getType(), diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7af80c0261..4c213b6594 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -378,7 +378,7 @@ public: SourceLocation Loc, DeclarationName Entity); QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, - SourceLocation Loc, DeclarationName Entity); + SourceRange Brackets, DeclarationName Entity); QualType BuildExtVectorType(QualType T, ExprArg ArraySize, SourceLocation AttrLoc); QualType BuildFunctionType(QualType T, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1fd569729a..f148e8d0e1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1568,9 +1568,18 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, return QualType(); llvm::APSInt &Res = EvalResult.Val.getInt(); - if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) - return Context.getConstantArrayType(VLATy->getElementType(), - Res, ArrayType::Normal, 0); + if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) { + Expr* ArySizeExpr = VLATy->getSizeExpr(); + // FIXME: here we could "steal" (how?) ArySizeExpr from the VLA, + // so as to transfer ownership to the ConstantArrayWithExpr. + // Alternatively, we could "clone" it (how?). + // Since we don't know how to do things above, we just use the + // very same Expr*. + return Context.getConstantArrayWithExprType(VLATy->getElementType(), + Res, ArySizeExpr, + ArrayType::Normal, 0, + VLATy->getBracketsRange()); + } SizeIsNegative = true; return QualType(); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index ecfdfd7ba0..5be07e3986 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -97,8 +97,9 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { llvm::APSInt ConstVal(32); ConstVal = StrLength; // Return a new array type (C99 6.7.8p22). - DeclT = S.Context.getConstantArrayType(IAT->getElementType(), ConstVal, - ArrayType::Normal, 0); + DeclT = S.Context.getConstantArrayWithoutExprType(IAT->getElementType(), + ConstVal, + ArrayType::Normal, 0); return; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 6c2dc77b4c..6ee50ab98c 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -421,7 +421,20 @@ InstantiateConstantArrayType(const ConstantArrayType *T) const { IntegerLiteral ArraySize(Size, SizeType, Loc); return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), &ArraySize, T->getIndexTypeQualifier(), - Loc, Entity); + SourceRange(), // FIXME: provide proper range? + Entity); +} + +QualType +TemplateTypeInstantiator::InstantiateConstantArrayWithExprType +(const ConstantArrayWithExprType *T) const { + return InstantiateConstantArrayType(T); +} + +QualType +TemplateTypeInstantiator::InstantiateConstantArrayWithoutExprType +(const ConstantArrayWithoutExprType *T) const { + return InstantiateConstantArrayType(T); } QualType @@ -432,8 +445,9 @@ InstantiateIncompleteArrayType(const IncompleteArrayType *T) const { return ElementType; return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), - 0, T->getIndexTypeQualifier(), - Loc, Entity); + 0, T->getIndexTypeQualifier(), + SourceRange(), // FIXME: provide proper range? + Entity); } QualType @@ -468,7 +482,9 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T) const { return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), InstantiatedArraySize.takeAs(), - T->getIndexTypeQualifier(), Loc, Entity); + T->getIndexTypeQualifier(), + SourceRange(), // FIXME: provide proper range? + Entity); } QualType diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 3756df870c..da61e6eb9e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -483,7 +483,8 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, /// returns a NULL type. QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, - SourceLocation Loc, DeclarationName Entity) { + SourceRange Brackets, DeclarationName Entity) { + SourceLocation Loc = Brackets.getBegin(); // C99 6.7.5.2p1: If the element type is an incomplete or function type, // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) if (RequireCompleteType(Loc, T, @@ -530,16 +531,16 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, llvm::APSInt ConstVal(32); if (!ArraySize) { if (ASM == ArrayType::Star) - T = Context.getVariableArrayType(T, 0, ASM, Quals); + T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets); else T = Context.getIncompleteArrayType(T, ASM, Quals); } else if (ArraySize->isValueDependent()) { - T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals); + T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets); } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) || (!T->isDependentType() && !T->isConstantSizeType())) { // Per C99, a variable array is an array with either a non-constant // size or an element type that has a non-constant-size - T = Context.getVariableArrayType(T, ArraySize, ASM, Quals); + T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); } else { // C99 6.7.5.2p1: If the expression is a constant expression, it shall // have a value greater than zero. @@ -555,7 +556,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, << ArraySize->getSourceRange(); } } - T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); + T = Context.getConstantArrayWithExprType(T, ConstVal, ArraySize, + ASM, Quals, Brackets); } // If this is not C99, extwarn about VLA's and C99 array size modifiers. if (!getLangOptions().C99) { @@ -923,7 +925,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, ASM = ArrayType::Normal; D.setInvalidType(true); } - T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals, DeclType.Loc, Name); + T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals, + SourceRange(DeclType.Loc, DeclType.EndLoc), Name); break; } case DeclaratorChunk::Function: {