summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-06-13 00:26:55 +0000
committerDouglas Gregor <dgregor@apple.com>2009-06-13 00:26:55 +0000
commit91772d1d76ffcbffe20f995c91b6dfb158c55598 (patch)
tree8241d540ef3a71dab976e4cd8cfcd5237e08b8b1 /clang/lib/Sema
parent4ca97c3b9e30b900f91389adb21246de2996188d (diff)
downloadbcm5719-llvm-91772d1d76ffcbffe20f995c91b6dfb158c55598.tar.gz
bcm5719-llvm-91772d1d76ffcbffe20f995c91b6dfb158c55598.zip
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. llvm-svn: 73274
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.h5
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp34
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp175
3 files changed, 211 insertions, 3 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 7e32c111292..d77036ff362 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2163,7 +2163,10 @@ public:
DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
TemplateDeductionInfo &Info);
-
+
+ void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
//===--------------------------------------------------------------------===//
// C++ Template Instantiation
//
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 54c61f6cd9b..78c1a9a97af 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2328,8 +2328,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
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 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
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.
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 4bbfd048c2f..d34019e36c1 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -881,3 +881,178 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
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);
+}
OpenPOWER on IntegriCloud