forked from OSchip/llvm-project
Delay checking of typedefs of dependent types. Fixes PR11630.
llvm-svn: 147281
This commit is contained in:
parent
8d302df4a4
commit
cde2c8f7d2
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue