diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-26 20:28:16 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-26 20:28:16 +0000 |
commit | 169f2190013d4474dfa04e2fd77e85a456269d41 (patch) | |
tree | 7b6dc96cc7f19024839d6664fc0ba94f6f24d2f4 /clang/lib | |
parent | eec0abefb65275a286db156515e9fa6ac3398957 (diff) | |
download | bcm5719-llvm-169f2190013d4474dfa04e2fd77e85a456269d41.tar.gz bcm5719-llvm-169f2190013d4474dfa04e2fd77e85a456269d41.zip |
Add a special-case diagnostic for one of the more obnoxious special cases of
unscoped enumeration members: an enumerator name which is visible in the
out-of-class definition of a member of a templated class might not actually
exist in the instantiation of that class, if the enumeration is also lexically
defined outside the class definition and is explicitly specialized.
Depending on the result of a CWG discussion, we may have a different resolution
for a class of problems in this area, but this fixes the immediate issue of a
crash-on-invalid / accepts-invalid (depending on +Asserts). Thanks to Johannes
Schaub for digging into the standard wording to find how this case is currently
specified to behave.
llvm-svn: 153461
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8729a39f9bc..e767f6a7d9f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3289,6 +3289,20 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, << D->getDeclName() << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); Diag(D->getLocation(), diag::note_non_instantiated_member_here); + } else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) { + // This enumeration constant was found when the template was defined, + // but can't be found in the instantiation. This can happen if an + // unscoped enumeration member is explicitly specialized. + EnumDecl *Enum = cast<EnumDecl>(ED->getLexicalDeclContext()); + EnumDecl *Spec = cast<EnumDecl>(FindInstantiatedDecl(Loc, Enum, + TemplateArgs)); + assert(Spec->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization); + Diag(Loc, diag::err_enumerator_does_not_exist) + << D->getDeclName() + << Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext())); + Diag(Spec->getLocation(), diag::note_enum_specialized_here) + << Context.getTypeDeclType(Spec); } else { // We should have found something, but didn't. llvm_unreachable("Unable to find instantiation of declaration!"); |