[cfe-commits] r132677 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
Douglas Gregor
dgregor at apple.com
Mon Jun 6 08:22:55 PDT 2011
Author: dgregor
Date: Mon Jun 6 10:22:55 2011
New Revision: 132677
URL: http://llvm.org/viewvc/llvm-project?rev=132677&view=rev
Log:
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>.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=132677&r1=132676&r2=132677&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jun 6 10:22:55 2011
@@ -1893,6 +1893,9 @@
def err_template_qualified_declarator_no_match : Error<
"nested name specifier '%0' for declaration does not refer into a class, "
"class template or class template partial specialization">;
+def err_specialize_member_of_template : Error<
+ "cannot specialize (with 'template<>') a member of an unspecialized "
+ "template">;
// C++ Class Template Partial Specialization
def err_default_arg_in_partial_spec : Error<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=132677&r1=132676&r2=132677&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jun 6 10:22:55 2011
@@ -4516,8 +4516,8 @@
if (!getLangOptions().CPlusPlus) {
// Perform semantic checking on the function declaration.
- bool isExplctSpecialization=false;
- CheckFunctionDeclaration(S, NewFD, Previous, isExplctSpecialization,
+ bool isExplicitSpecialization=false;
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
Redeclaration);
assert((NewFD->isInvalidDecl() || !Redeclaration ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
@@ -4540,7 +4540,9 @@
HasExplicitTemplateArgs = true;
- if (FunctionTemplate) {
+ if (NewFD->isInvalidDecl()) {
+ HasExplicitTemplateArgs = false;
+ } else if (FunctionTemplate) {
// Function template with explicit template arguments.
Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=132677&r1=132676&r2=132677&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Jun 6 10:22:55 2011
@@ -1610,6 +1610,7 @@
// 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 @@
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 @@
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];
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp?rev=132677&r1=132676&r2=132677&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp Mon Jun 6 10:22:55 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
template<class T> struct A {
void f(T);
template<class X1> void g1(T, X1);
@@ -24,3 +24,15 @@
// member specialization even if defined in class definition
template<> void A<int>::h(int) { }
+
+namespace PR10024 {
+ template <typename T>
+ struct Test{
+ template <typename U>
+ void get(U i) {}
+ };
+
+ template <typename T>
+ template <>
+ void Test<T>::get<double>(double i) {} // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}}
+}
More information about the cfe-commits
mailing list