forked from OSchip/llvm-project
When de-serializing a type that is supposed to be canonical, call
getCanonicalType() to make sure that the type we got back is actually canonical. This is the case for most types, which always build a canonical type when given canonical components. However, some types that involve expressions in their canonicalization (e.g., array types with dependent sizes) don't always build canonical types from canonical components, because there is no such thing as a "canonical" expression. Therefore, we do this extra mapping to ensure that the canonical types we store are actually canonical. llvm-svn: 117344
This commit is contained in:
parent
5c01cb6b77
commit
f86c939bff
|
@ -1522,11 +1522,12 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
|
|||
DependentSizedArrayType *Canon = 0;
|
||||
llvm::FoldingSetNodeID ID;
|
||||
|
||||
QualType CanonicalEltTy = getCanonicalType(EltTy);
|
||||
if (NumElts) {
|
||||
// Dependently-sized array types that do not have a specified
|
||||
// number of elements will have their sizes deduced from an
|
||||
// initializer.
|
||||
DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
|
||||
DependentSizedArrayType::Profile(ID, *this, CanonicalEltTy, ASM,
|
||||
EltTypeQuals, NumElts);
|
||||
|
||||
Canon = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
@ -1539,28 +1540,28 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
|
|||
New = new (*this, TypeAlignment)
|
||||
DependentSizedArrayType(*this, EltTy, QualType(Canon, 0),
|
||||
NumElts, ASM, EltTypeQuals, Brackets);
|
||||
} else {
|
||||
QualType CanonEltTy = getCanonicalType(EltTy);
|
||||
if (CanonEltTy == EltTy) {
|
||||
New = new (*this, TypeAlignment)
|
||||
DependentSizedArrayType(*this, EltTy, QualType(),
|
||||
NumElts, ASM, EltTypeQuals, Brackets);
|
||||
|
||||
if (NumElts) {
|
||||
DependentSizedArrayType *CanonCheck
|
||||
= DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!CanonCheck && "Dependent-sized canonical array type broken");
|
||||
(void)CanonCheck;
|
||||
DependentSizedArrayTypes.InsertNode(New, InsertPos);
|
||||
}
|
||||
} else {
|
||||
QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts,
|
||||
ASM, EltTypeQuals,
|
||||
SourceRange());
|
||||
New = new (*this, TypeAlignment)
|
||||
DependentSizedArrayType(*this, EltTy, Canon,
|
||||
NumElts, ASM, EltTypeQuals, Brackets);
|
||||
} else if (CanonicalEltTy == EltTy) {
|
||||
// This is a canonical type. Record it.
|
||||
New = new (*this, TypeAlignment)
|
||||
DependentSizedArrayType(*this, EltTy, QualType(),
|
||||
NumElts, ASM, EltTypeQuals, Brackets);
|
||||
|
||||
if (NumElts) {
|
||||
#ifndef NDEBUG
|
||||
DependentSizedArrayType *CanonCheck
|
||||
= DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!CanonCheck && "Dependent-sized canonical array type broken");
|
||||
(void)CanonCheck;
|
||||
#endif
|
||||
DependentSizedArrayTypes.InsertNode(New, InsertPos);
|
||||
}
|
||||
} else {
|
||||
QualType Canon = getDependentSizedArrayType(CanonicalEltTy, NumElts,
|
||||
ASM, EltTypeQuals,
|
||||
SourceRange());
|
||||
New = new (*this, TypeAlignment)
|
||||
DependentSizedArrayType(*this, EltTy, Canon,
|
||||
NumElts, ASM, EltTypeQuals, Brackets);
|
||||
}
|
||||
|
||||
Types.push_back(New);
|
||||
|
|
|
@ -2764,6 +2764,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
|
|||
}
|
||||
TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0]));
|
||||
QualType Canonical = GetType(Record[1]);
|
||||
if (!Canonical.isNull())
|
||||
Canonical = Context->getCanonicalType(Canonical);
|
||||
return Context->getTypedefType(Decl, Canonical);
|
||||
}
|
||||
|
||||
|
@ -2867,6 +2869,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
|
|||
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
|
||||
const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx);
|
||||
QualType Canon = GetType(Record[Idx++]);
|
||||
if (!Canon.isNull())
|
||||
Canon = Context->getCanonicalType(Canon);
|
||||
return Context->getDependentNameType(Keyword, NNS, Name, Canon);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ struct A {
|
|||
static T my_templf(T x) { return x; }
|
||||
};
|
||||
|
||||
void test() {
|
||||
void test(const int (&a6)[17]) {
|
||||
int x = templ_f<int, 5>(3);
|
||||
|
||||
S<char, float>::templ();
|
||||
|
@ -32,6 +32,8 @@ void test() {
|
|||
s3.m();
|
||||
|
||||
TS5 ts(0);
|
||||
|
||||
S6<const int[17]>::t2 b6 = a6;
|
||||
}
|
||||
|
||||
template struct S4<int>;
|
||||
|
|
|
@ -150,3 +150,17 @@ struct TS5 {
|
|||
template<class T> void f_PR8134(T);
|
||||
template<class T> void f_PR8134(T);
|
||||
void g_PR8134() { f_PR8134(0); f_PR8134('x'); }
|
||||
|
||||
// rdar8580149
|
||||
template <typename T>
|
||||
struct S6;
|
||||
|
||||
template <typename T, unsigned N>
|
||||
struct S6<const T [N]>
|
||||
{
|
||||
private:
|
||||
typedef const T t1[N];
|
||||
public:
|
||||
typedef t1& t2;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue