diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-06 15:22:55 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-06 15:22:55 +0000 |
commit | 522d5eb7c3c2d255899140cc83e0f9c2166498c8 (patch) | |
tree | a1fd072782215149661f6a16c107a27f492da27f /clang/lib/Sema/SemaTemplate.cpp | |
parent | bd375f1a3f2d978c77d573329ad77e37f29c1c41 (diff) | |
download | bcm5719-llvm-522d5eb7c3c2d255899140cc83e0f9c2166498c8.tar.gz bcm5719-llvm-522d5eb7c3c2d255899140cc83e0f9c2166498c8.zip |
Diagnose the condition in C++ [temp.expl.spec]p16 that prohibits
specializing a member of an unspecialized template, and recover from
such errors without crashing. Fixes PR10024 / <rdar://problem/9509761>.
llvm-svn: 132677
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3761740d8c0..8213f3266f1 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1610,6 +1610,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // such a member, the member declaration shall be preceded by a // template<> for each enclosing class template that is // explicitly specialized. + bool SawNonEmptyTemplateParameterList = false; unsigned ParamIdx = 0; for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes; ++TypeIdx) { @@ -1671,6 +1672,26 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, NeedNonemptyTemplateHeader = false; } + // C++ [temp.expl.spec]p16: + // In an explicit specialization declaration for a member of a class + // template or a member template that ap- pears in namespace scope, the + // member template and some of its enclosing class templates may remain + // unspecialized, except that the declaration shall not explicitly + // specialize a class member template if its en- closing class templates + // are not explicitly specialized as well. + if (ParamIdx < NumParamLists) { + if (ParamLists[ParamIdx]->size() == 0) { + if (SawNonEmptyTemplateParameterList) { + Diag(DeclLoc, diag::err_specialize_member_of_template) + << ParamLists[ParamIdx]->getSourceRange(); + Invalid = true; + IsExplicitSpecialization = false; + return 0; + } + } else + SawNonEmptyTemplateParameterList = true; + } + if (NeedEmptyTemplateHeader) { // If we're on the last of the types, and we need a 'template<>' header // here, then it's an explicit specialization. @@ -1787,6 +1808,22 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, Invalid = true; } + // C++ [temp.expl.spec]p16: + // In an explicit specialization declaration for a member of a class + // template or a member template that ap- pears in namespace scope, the + // member template and some of its enclosing class templates may remain + // unspecialized, except that the declaration shall not explicitly + // specialize a class member template if its en- closing class templates + // are not explicitly specialized as well. + if (ParamLists[NumParamLists - 1]->size() == 0 && + SawNonEmptyTemplateParameterList) { + Diag(DeclLoc, diag::err_specialize_member_of_template) + << ParamLists[ParamIdx]->getSourceRange(); + Invalid = true; + IsExplicitSpecialization = false; + return 0; + } + // Return the last template parameter list, which corresponds to the // entity being declared. return ParamLists[NumParamLists - 1]; |