forked from OSchip/llvm-project
Keep track of the Expr used to describe the size of an array type,
from Enea Zaffanella! llvm-svn: 74831
This commit is contained in:
parent
19623dc075
commit
04318256b7
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -475,6 +475,8 @@ ASTContext::getTypeInfo(const Type *T) {
|
|||
Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
|
||||
break;
|
||||
|
||||
case Type::ConstantArrayWithExpr:
|
||||
case Type::ConstantArrayWithoutExpr:
|
||||
case Type::ConstantArray: {
|
||||
const ConstantArrayType *CAT = cast<ConstantArrayType>(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<DependentSizedArrayType>(AT))
|
||||
return getDependentSizedArrayType(NewEltTy, DSAT->getSizeExpr(),
|
||||
return getDependentSizedArrayType(NewEltTy,
|
||||
DSAT->getSizeExpr(),
|
||||
DSAT->getSizeModifier(),
|
||||
DSAT->getIndexTypeQualifier());
|
||||
DSAT->getIndexTypeQualifier(),
|
||||
DSAT->getBracketsRange());
|
||||
|
||||
VariableArrayType *VAT = cast<VariableArrayType>(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<IncompleteArrayType>(ATy))
|
||||
return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
|
||||
IAT->getSizeModifier(),
|
||||
IAT->getIndexTypeQualifier()));
|
||||
IAT->getIndexTypeQualifier()));
|
||||
|
||||
if (const DependentSizedArrayType *DSAT
|
||||
= dyn_cast<DependentSizedArrayType>(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<VariableArrayType>(ATy);
|
||||
return cast<ArrayType>(getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
|
||||
return cast<ArrayType>(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);
|
||||
|
|
|
@ -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 += "[]";
|
||||
|
||||
|
|
|
@ -780,6 +780,8 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
|
|||
return Slot = CreateType(cast<FunctionType>(Ty), Unit);
|
||||
|
||||
case Type::ConstantArray:
|
||||
case Type::ConstantArrayWithExpr:
|
||||
case Type::ConstantArrayWithoutExpr:
|
||||
case Type::VariableArray:
|
||||
case Type::IncompleteArray:
|
||||
return Slot = CreateType(cast<ArrayType>(Ty), Unit);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Expr>(),
|
||||
T->getIndexTypeQualifier(), Loc, Entity);
|
||||
T->getIndexTypeQualifier(),
|
||||
SourceRange(), // FIXME: provide proper range?
|
||||
Entity);
|
||||
}
|
||||
|
||||
QualType
|
||||
|
|
|
@ -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: {
|
||||
|
|
Loading…
Reference in New Issue