llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
std::vector<VariableArrayType*> VariableArrayTypes;
- std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
+ llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes;
llvm::FoldingSet<VectorType> VectorTypes;
llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
/// until template instantiation occurs, at which point this will
/// become either a ConstantArrayType or a VariableArrayType.
class DependentSizedArrayType : public ArrayType {
+ ASTContext &Context;
+
/// 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,
+ DependentSizedArrayType(ASTContext &Context, QualType et, QualType can,
+ Expr *e, ArraySizeModifier sm, unsigned tq,
SourceRange brackets)
: ArrayType(DependentSizedArray, et, can, sm, tq),
- SizeExpr((Stmt*) e), Brackets(brackets) {}
+ Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
virtual void Destroy(ASTContext& C);
friend class StmtIteratorBase;
+
void Profile(llvm::FoldingSetNodeID &ID) {
- assert(0 && "Cannnot unique DependentSizedArrayTypes.");
+ Profile(ID, Context, getElementType(),
+ getSizeModifier(), getIndexTypeQualifier(), getSizeExpr());
}
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ QualType ET, ArraySizeModifier SizeMod,
+ unsigned TypeQuals, Expr *E);
};
/// DependentSizedExtVectorType - This type represent an extended vector type
/// getDependentSizedArrayType - Returns a non-unique reference to
/// 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.
+/// type.
QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) &&
"Size must be type- or value-dependent!");
- // Since we don't unique expressions, it isn't possible to unique
- // dependently-sized array types.
-
- DependentSizedArrayType *New =
- new (*this,8) DependentSizedArrayType(EltTy, QualType(),
- NumElts, ASM, EltTypeQuals,
- Brackets);
+ llvm::FoldingSetNodeID ID;
+ DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
+ EltTypeQuals, NumElts);
- DependentSizedArrayTypes.push_back(New);
+ void *InsertPos = 0;
+ DependentSizedArrayType *Canon
+ = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+ DependentSizedArrayType *New;
+ if (Canon) {
+ // We already have a canonical version of this array type; use it as
+ // the canonical type for a newly-built type.
+ New = new (*this,8) DependentSizedArrayType(*this, EltTy,
+ QualType(Canon, 0),
+ NumElts, ASM, EltTypeQuals,
+ Brackets);
+ } else {
+ QualType CanonEltTy = getCanonicalType(EltTy);
+ if (CanonEltTy == EltTy) {
+ New = new (*this,8) DependentSizedArrayType(*this, EltTy, QualType(),
+ NumElts, ASM, EltTypeQuals,
+ Brackets);
+ DependentSizedArrayTypes.InsertNode(New, InsertPos);
+ } else {
+ QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts,
+ ASM, EltTypeQuals,
+ SourceRange());
+ New = new (*this,8) DependentSizedArrayType(*this, EltTy, Canon,
+ NumElts, ASM, EltTypeQuals,
+ Brackets);
+ }
+ }
+
Types.push_back(New);
return QualType(New, 0);
}
C.Deallocate(this);
}
+void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
+ ASTContext &Context,
+ QualType ET,
+ ArraySizeModifier SizeMod,
+ unsigned TypeQuals,
+ Expr *E) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ E->Profile(ID, Context, true);
+}
+
void DependentSizedExtVectorType::Destroy(ASTContext& C) {
// FIXME: Deallocate size expression, once we're cloning properly.
// if (SizeExpr)
void f0(T x, __typeof__((f)(N)) y) { }
template<typename U, U M>
-void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}}
\ No newline at end of file
+void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}}
+
+// Test dependently-sized array canonicalization
+template<typename T, int N, int M>
+void f1(T (&array)[N + M]) { } // expected-note{{previous}}
+
+template<typename T, int N, int M>
+void f1(T (&array)[M + N]) { }
+
+template<typename T, int M, int N>
+void f1(T (&array)[M + N]) { } // expected-error{{redefinition}}