Delay checking of typedefs of dependent types. Fixes PR11630.

llvm-svn: 147281
This commit is contained in:
Rafael Espindola 2011-12-26 22:42:47 +00:00
parent 8d302df4a4
commit cde2c8f7d2
4 changed files with 67 additions and 21 deletions

View File

@ -1326,6 +1326,7 @@ public:
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo);
bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);

View File

@ -1368,6 +1368,30 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
return New;
}
bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
OldType = OldTypedef->getUnderlyingType();
else
OldType = Context.getTypeDeclType(Old);
QualType NewType = New->getUnderlyingType();
if (OldType != NewType &&
!OldType->isDependentType() &&
!NewType->isDependentType() &&
Context.getCanonicalType(OldType) !=
Context.getCanonicalType(NewType)) {
int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
<< Kind << NewType << OldType;
if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
return true;
}
return false;
}
/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the
/// same name and scope as a previous declaration 'Old'. Figure out
/// how to resolve this situation, merging decls or emitting
@ -1426,28 +1450,10 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
if (Old->isInvalidDecl())
return New->setInvalidDecl();
// Determine the "old" type we'll use for checking and diagnostics.
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
OldType = OldTypedef->getUnderlyingType();
else
OldType = Context.getTypeDeclType(Old);
// If the typedef types are not identical, reject them in all languages and
// with any extensions enabled.
if (OldType != New->getUnderlyingType() &&
Context.getCanonicalType(OldType) !=
Context.getCanonicalType(New->getUnderlyingType())) {
int Kind = 0;
if (isa<TypeAliasDecl>(Old))
Kind = 1;
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
<< Kind << New->getUnderlyingType() << OldType;
if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
if (isIncompatibleTypedef(Old, New))
return;
// The types match. Link up the redeclaration chain if the old
// declaration was a typedef.

View File

@ -169,7 +169,12 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
if (!InstPrev)
return 0;
Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev));
TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
// If the typedef types are not identical, reject them.
SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef);
Typedef->setPreviousDeclaration(InstPrevTypedef);
}
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);

View File

@ -59,3 +59,37 @@ template<typename T>
typedef T f(T t) { return t; } // expected-error {{function definition declared 'typedef'}}
int k = f(0);
int k2 = k;
namespace PR11630 {
template <class T>
struct S
{
static const unsigned C = 1;
static void f()
{
typedef int q[C == 1 ? 1 : -1]; // expected-note{{previous definition is here}}
typedef int q[C >= 1 ? 2 : -2]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}}
typedef int n[C == 1 ? 1 : -1];
typedef int n[C >= 1 ? 1 : -1];
}
};
template <int T>
struct S2
{
static void f()
{
typedef int q[1]; // expected-note{{previous definition is here}}
typedef int q[T]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}}
}
};
void f() {
S<int> a;
a.f(); // expected-note{{in instantiation of member function 'PR11630::S<int>::f' requested here}}
S2<1> b;
b.f();
S2<2> b2;
b2.f(); // expected-note{{in instantiation of member function 'PR11630::S2<2>::f' requested here}}
}
}