[cfe-commits] r73274 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp test/SemaTemplate/temp_class_spec_neg.cpp
Douglas Gregor
dgregor at apple.com
Fri Jun 12 17:26:55 PDT 2009
Author: dgregor
Date: Fri Jun 12 19:26:55 2009
New Revision: 73274
URL: http://llvm.org/viewvc/llvm-project?rev=73274&view=rev
Log:
When some template parameters of a class template partial
specialization cannot be deduced, produce a warning noting that the
affected class template partial specialization will never be used.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=73274&r1=73273&r2=73274&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 12 19:26:55 2009
@@ -770,6 +770,12 @@
"class template partial specialization does not specialize any template "
"argument; to %select{declare|define}0 the primary template, remove the "
"template argument list">;
+def warn_partial_specs_not_deducible : Warning<
+ "class template partial specialization contains "
+ "%select{a template parameter|template parameters}0 that can not be "
+ "deduced; this partial specialization will never be used">;
+def note_partial_spec_unused_parameter : Note<
+ "non-deducible template parameter %0">;
def unsup_template_partial_spec_ordering : Error<
"partial ordering of class template partial specializations is not yet "
"supported">;
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=73274&r1=73273&r2=73274&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Jun 12 19:26:55 2009
@@ -2163,7 +2163,10 @@
DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
TemplateDeductionInfo &Info);
-
+
+ void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
//===--------------------------------------------------------------------===//
// C++ Template Instantiation
//
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=73274&r1=73273&r2=73274&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Jun 12 19:26:55 2009
@@ -2328,8 +2328,6 @@
Specialization->setLocation(TemplateNameLoc);
PrevDecl = 0;
} else if (isPartialSpecialization) {
- // FIXME: extra checking for partial specializations
-
// Create a new class template partial specialization declaration node.
TemplateParameterList *TemplateParams
= static_cast<TemplateParameterList*>(*TemplateParameterLists.get());
@@ -2351,6 +2349,38 @@
ClassTemplate->getPartialSpecializations().InsertNode(Partial, InsertPos);
}
Specialization = Partial;
+
+ // Check that all of the template parameters of the class template
+ // partial specialization are deducible from the template
+ // arguments. If not, this class template partial specialization
+ // will never be used.
+ llvm::SmallVector<bool, 8> DeducibleParams;
+ DeducibleParams.resize(TemplateParams->size());
+ MarkDeducedTemplateParameters(Partial->getTemplateArgs(), DeducibleParams);
+ unsigned NumNonDeducible = 0;
+ for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I)
+ if (!DeducibleParams[I])
+ ++NumNonDeducible;
+
+ if (NumNonDeducible) {
+ Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
+ << (NumNonDeducible > 1)
+ << SourceRange(TemplateNameLoc, RAngleLoc);
+ for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+ if (!DeducibleParams[I]) {
+ NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+ if (Param->getDeclName())
+ Diag(Param->getLocation(),
+ diag::note_partial_spec_unused_parameter)
+ << Param->getDeclName();
+ else
+ Diag(Param->getLocation(),
+ diag::note_partial_spec_unused_parameter)
+ << std::string("<anonymous>");
+ }
+ }
+ }
+
} else {
// Create a new class template specialization declaration node for
// this explicit specialization.
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=73274&r1=73273&r2=73274&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Jun 12 19:26:55 2009
@@ -881,3 +881,178 @@
return TDK_Success;
}
+
+static void
+MarkDeducedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
+/// \brief Mark the template arguments that are deduced by the given
+/// expression.
+static void
+MarkDeducedTemplateParameters(Expr *E, llvm::SmallVectorImpl<bool> &Deduced) {
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+ if (!E)
+ return;
+
+ NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ if (!NTTP)
+ return;
+
+ Deduced[NTTP->getIndex()] = true;
+}
+
+/// \brief Mark the template parameters that are deduced by the given
+/// type.
+static void
+MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ // Non-dependent types have nothing deducible
+ if (!T->isDependentType())
+ return;
+
+ T = SemaRef.Context.getCanonicalType(T);
+ switch (T->getTypeClass()) {
+ case Type::ExtQual:
+ MarkDeducedTemplateParameters(SemaRef,
+ QualType(cast<ExtQualType>(T.getTypePtr())->getBaseType(), 0),
+ Deduced);
+ break;
+
+ case Type::Pointer:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<PointerType>(T.getTypePtr())->getPointeeType(),
+ Deduced);
+ break;
+
+ case Type::BlockPointer:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<BlockPointerType>(T.getTypePtr())->getPointeeType(),
+ Deduced);
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<ReferenceType>(T.getTypePtr())->getPointeeType(),
+ Deduced);
+ break;
+
+ case Type::MemberPointer: {
+ const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
+ MarkDeducedTemplateParameters(SemaRef, MemPtr->getPointeeType(), Deduced);
+ MarkDeducedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
+ Deduced);
+ break;
+ }
+
+ case Type::DependentSizedArray:
+ MarkDeducedTemplateParameters(
+ cast<DependentSizedArrayType>(T.getTypePtr())->getSizeExpr(),
+ Deduced);
+ // Fall through to check the element type
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<ArrayType>(T.getTypePtr())->getElementType(),
+ Deduced);
+ break;
+
+ case Type::Vector:
+ case Type::ExtVector:
+ MarkDeducedTemplateParameters(SemaRef,
+ cast<VectorType>(T.getTypePtr())->getElementType(),
+ Deduced);
+ break;
+
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T.getTypePtr());
+ MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced);
+ for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
+ MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced);
+ break;
+ }
+
+ case Type::TemplateTypeParm:
+ Deduced[cast<TemplateTypeParmType>(T.getTypePtr())->getIndex()] = true;
+ break;
+
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *Spec
+ = cast<TemplateSpecializationType>(T.getTypePtr());
+ if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl())
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
+ Deduced[TTP->getIndex()] = true;
+
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ MarkDeducedTemplateParameters(SemaRef, Spec->getArg(I), Deduced);
+
+ break;
+ }
+
+ // None of these types have any deducible parts.
+ case Type::Builtin:
+ case Type::FixedWidthInt:
+ case Type::Complex:
+ case Type::VariableArray:
+ case Type::FunctionNoProto:
+ case Type::Record:
+ case Type::Enum:
+ case Type::Typename:
+ case Type::ObjCInterface:
+ case Type::ObjCQualifiedInterface:
+ case Type::ObjCQualifiedId:
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ break;
+ }
+}
+
+/// \brief Mark the template parameters that are deduced by this
+/// template argument.
+static void
+MarkDeducedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ switch (TemplateArg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ break;
+
+ case TemplateArgument::Type:
+ MarkDeducedTemplateParameters(SemaRef, TemplateArg.getAsType(), Deduced);
+ break;
+
+ case TemplateArgument::Declaration:
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl()))
+ Deduced[TTP->getIndex()] = true;
+ break;
+
+ case TemplateArgument::Expression:
+ MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced);
+ break;
+ }
+}
+
+/// \brief Mark the template parameters can be deduced by the given
+/// template argument list.
+///
+/// \param TemplateArgs the template argument list from which template
+/// parameters will be deduced.
+///
+/// \param Deduced a bit vector whose elements will be set to \c true
+/// to indicate when the corresponding template parameter will be
+/// deduced.
+void
+Sema::MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ ::MarkDeducedTemplateParameters(*this, TemplateArgs[I], Deduced);
+}
Modified: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp?rev=73274&r1=73273&r2=73274&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp Fri Jun 12 19:26:55 2009
@@ -39,3 +39,7 @@
int N = 17, // expected-error{{default template argument}}
template<typename X> class TT = ::vector> // expected-error{{default template argument}}
struct Test0<T*, N, TT> { };
+
+template<typename T> struct Test1;
+template<typename T, typename U> // expected-note{{non-deducible}}
+ struct Test1<T*> { }; // expected-warning{{never be used}}
More information about the cfe-commits
mailing list