diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-26 04:08:46 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-26 04:08:46 +0000 |
commit | 258a744bbd6dbfb675d3c39da021321f2b317dae (patch) | |
tree | 08bd61324793a416d0b0e8f04650ea5d8f96bc0c /clang/lib/Sema | |
parent | eb75cc26af4ca8f5cba1b52f42809329ba48c583 (diff) | |
download | bcm5719-llvm-258a744bbd6dbfb675d3c39da021321f2b317dae.tar.gz bcm5719-llvm-258a744bbd6dbfb675d3c39da021321f2b317dae.zip |
Delay checking of dependent underlying types for redeclarations of member
enumerations in templates until the template is instantiated.
llvm-svn: 153426
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 21 |
2 files changed, 19 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 68b27ef1f98..e92b3e4acab 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7780,7 +7780,9 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, } if (IsFixed && Prev->isFixed()) { - if (!Context.hasSameUnqualifiedType(EnumUnderlyingTy, + if (!EnumUnderlyingTy->isDependentType() && + !Prev->getIntegerType()->isDependentType() && + !Context.hasSameUnqualifiedType(EnumUnderlyingTy, Prev->getIntegerType())) { Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch) << EnumUnderlyingTy << Prev->getIntegerType(); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index ebc43d443db..caf134e0259 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -588,9 +588,20 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { if (SubstQualifier(D, Enum)) return 0; Owner->addDecl(Enum); - // FIXME: If this is a redeclaration: - // CheckEnumRedeclaration(Enum->getLocation(), Enum->isScoped(), - // Enum->getIntegerType(), Prev); + EnumDecl *Def = D->getDefinition(); + if (Def && Def != D) { + // If this is an out-of-line definition of an enum member template, check + // that the underlying types match in the instantiation of both + // declarations. + if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) { + SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); + QualType DefnUnderlying = + SemaRef.SubstType(TI->getType(), TemplateArgs, + UnderlyingLoc, DeclarationName()); + SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), + DefnUnderlying, Enum); + } + } if (D->getDeclContext()->isFunctionOrMethod()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); @@ -600,8 +611,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { // not the definitions of scoped member enumerations. // FIXME: There appears to be no wording for what happens for an enum defined // within a block scope, but we treat that like a member of a class template. - if (!Enum->isScoped() && D->getDefinition()) - InstantiateEnumDefinition(Enum, D); + if (!Enum->isScoped() && Def) + InstantiateEnumDefinition(Enum, Def); return Enum; } |