diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-06-13 00:26:55 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-06-13 00:26:55 +0000 |
| commit | 91772d1d76ffcbffe20f995c91b6dfb158c55598 (patch) | |
| tree | 8241d540ef3a71dab976e4cd8cfcd5237e08b8b1 /clang/lib/Sema | |
| parent | 4ca97c3b9e30b900f91389adb21246de2996188d (diff) | |
| download | bcm5719-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.h | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 34 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 175 |
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); +} |

