diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 18 | ||||
-rw-r--r-- | clang/test/SemaCXX/enum-scoped.cpp | 24 |
2 files changed, 39 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index caf134e0259..8729a39f9bc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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<EnumDecl>(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/clang/test/SemaCXX/enum-scoped.cpp b/clang/test/SemaCXX/enum-scoped.cpp index c842dcde848..ebe92453585 100644 --- a/clang/test/SemaCXX/enum-scoped.cpp +++ b/clang/test/SemaCXX/enum-scoped.cpp @@ -221,3 +221,27 @@ namespace test9 { // never instantiate the definitions of S<short>::ET nor S<short>::Eint. S<short> s; // expected-note {{in instantiation of}} } + +namespace test10 { + template<typename T> 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>(); + int l = f<short>(); // expected-note {{here}} + + template<typename T> 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>(); + int n = g<short>(); // expected-note {{here}} +} |