From 38f0df352fadc546c5666079fb22de5ec1819d92 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 26 Mar 2012 04:58:10 +0000 Subject: [PATCH] Handle instantiations of redeclarations of forward-declared enumerations within templated functions. Build a redeclaration chain, and only instantiate the definition of the enum when visiting the defining declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153427 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiateDecl.cpp | 18 +++++++++++++++--- test/SemaCXX/enum-scoped.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index caf134e025..8729a39f9b 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -558,9 +558,18 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { } Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { + EnumDecl *PrevDecl = 0; + if (D->getPreviousDecl()) { + NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), + D->getPreviousDecl(), + TemplateArgs); + if (!Prev) return 0; + PrevDecl = cast(Prev); + } + EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), - /*PrevDecl=*/0, D->isScoped(), + PrevDecl, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) { @@ -610,8 +619,11 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { // specialization causes the implicit instantiation of the declarations, but // 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() && Def) + // within a block scope, but we treat that much like a member template. Only + // instantiate the definition when visiting the definition in that case, since + // we will visit all redeclarations. + if (!Enum->isScoped() && Def && + (!D->getDeclContext()->isFunctionOrMethod() || D->isCompleteDefinition())) InstantiateEnumDefinition(Enum, Def); return Enum; diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index c842dcde84..ebe9245358 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -221,3 +221,27 @@ namespace test9 { // never instantiate the definitions of S::ET nor S::Eint. S s; // expected-note {{in instantiation of}} } + +namespace test10 { + template int f() { + enum E : int; + enum E : T; // expected-note {{here}} + E x; + enum E : int { e }; // expected-error {{different underlying}} + x = e; + return x; + } + int k = f(); + int l = f(); // expected-note {{here}} + + template int g() { + enum class E : int; + enum class E : T; // expected-note {{here}} + E x; + enum class E : int { e }; // expected-error {{different underlying}} + x = E::e; + return (int)x; + } + int m = g(); + int n = g(); // expected-note {{here}} +} -- 2.40.0