diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-14 21:25:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-14 21:25:05 +0000 |
commit | e73bb60de3c7c60453a86e097fc428d1cd367a42 (patch) | |
tree | f7e4949ea0c339db5716fad4e95e54da3384643a | |
parent | b191e2dda9f4dc033cb21f9625a78fe80d4ac105 (diff) |
Refactor MarkDeductedTemplateParameters into
MarkUsedTemplateParameters, which is able to mark template parameters
used within non-deduced contexts as well as deduced contexts. Use this
to finish the implementation of [temp.deduct.partial]p11.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81794 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 203 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp | 16 |
4 files changed, 155 insertions, 72 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0ef20ee9cb..c0719d4577 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2732,8 +2732,9 @@ public: FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC); - void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs, - llvm::SmallVectorImpl<bool> &Deduced); + void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Deduced); //===--------------------------------------------------------------------===// // C++ Template Instantiation diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f8b48b218a..ab791a468c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2720,7 +2720,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // will never be used. llvm::SmallVector<bool, 8> DeducibleParams; DeducibleParams.resize(TemplateParams->size()); - MarkDeducedTemplateParameters(Partial->getTemplateArgs(), DeducibleParams); + MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, + DeducibleParams); unsigned NumNonDeducible = 0; for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) if (!DeducibleParams[I]) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index d9d1483c67..0ca7fccd50 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1677,8 +1677,9 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context, } static void -MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, - llvm::SmallVectorImpl<bool> &Deduced); +MarkUsedTemplateParameters(Sema &SemaRef, QualType T, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Deduced); /// \brief Determine whether the function template \p FT1 is at least as /// specialized as \p FT2. @@ -1763,25 +1764,25 @@ static bool isAtLeastAsSpecializedAs(Sema &S, return true; } - // FIXME: MarkDeducedTemplateParameters needs to become - // MarkUsedTemplateParameters with a flag that tells us whether to mark - // template parameters that are used in non-deduced contexts. + // Figure out which template parameters were used. llvm::SmallVector<bool, 4> UsedParameters; UsedParameters.resize(TemplateParams->size()); switch (TPOC) { case TPOC_Call: { unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs()); for (unsigned I = 0; I != NumParams; ++I) - ::MarkDeducedTemplateParameters(S, Proto2->getArgType(I), UsedParameters); + ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, + UsedParameters); break; } case TPOC_Conversion: - ::MarkDeducedTemplateParameters(S, Proto2->getResultType(), UsedParameters); + ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false, + UsedParameters); break; case TPOC_Other: - ::MarkDeducedTemplateParameters(S, FD2->getType(), UsedParameters); + ::MarkUsedTemplateParameters(S, FD2->getType(), false, UsedParameters); break; } @@ -1869,15 +1870,20 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, } static void -MarkDeducedTemplateParameters(Sema &SemaRef, - const TemplateArgument &TemplateArg, - llvm::SmallVectorImpl<bool> &Deduced); +MarkUsedTemplateParameters(Sema &SemaRef, + const TemplateArgument &TemplateArg, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used); -/// \brief Mark the template arguments that are deduced by the given +/// \brief Mark the template parameters that are used by the given /// expression. static void -MarkDeducedTemplateParameters(const Expr *E, - llvm::SmallVectorImpl<bool> &Deduced) { +MarkUsedTemplateParameters(Sema &SemaRef, + const Expr *E, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used) { + // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to + // find other occurrences of template parameters. const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); if (!E) return; @@ -1887,14 +1893,51 @@ MarkDeducedTemplateParameters(const Expr *E, if (!NTTP) return; - Deduced[NTTP->getIndex()] = true; + Used[NTTP->getIndex()] = true; } -/// \brief Mark the template parameters that are deduced by the given +/// \brief Mark the template parameters that are used by the given +/// nested name specifier. +static void +MarkUsedTemplateParameters(Sema &SemaRef, + NestedNameSpecifier *NNS, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used) { + if (!NNS) + return; + + MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Used); + MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0), + OnlyDeduced, Used); +} + +/// \brief Mark the template parameters that are used by the given +/// template name. +static void +MarkUsedTemplateParameters(Sema &SemaRef, + TemplateName Name, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used) { + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast<TemplateTemplateParmDecl>(Template)) + Used[TTP->getIndex()] = true; + return; + } + + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) + MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, Used); +} + +/// \brief Mark the template parameters that are used by the given /// type. static void -MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, - llvm::SmallVectorImpl<bool> &Deduced) { +MarkUsedTemplateParameters(Sema &SemaRef, QualType T, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used) { + if (T.isNull()) + return; + // Non-dependent types have nothing deducible if (!T->isDependentType()) return; @@ -1902,100 +1945,118 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, T = SemaRef.Context.getCanonicalType(T); switch (T->getTypeClass()) { case Type::ExtQual: - MarkDeducedTemplateParameters(SemaRef, - QualType(cast<ExtQualType>(T)->getBaseType(), 0), - Deduced); + MarkUsedTemplateParameters(SemaRef, + QualType(cast<ExtQualType>(T)->getBaseType(), 0), + OnlyDeduced, + Used); break; case Type::Pointer: - MarkDeducedTemplateParameters(SemaRef, - cast<PointerType>(T)->getPointeeType(), - Deduced); + MarkUsedTemplateParameters(SemaRef, + cast<PointerType>(T)->getPointeeType(), + OnlyDeduced, + Used); break; case Type::BlockPointer: - MarkDeducedTemplateParameters(SemaRef, - cast<BlockPointerType>(T)->getPointeeType(), - Deduced); + MarkUsedTemplateParameters(SemaRef, + cast<BlockPointerType>(T)->getPointeeType(), + OnlyDeduced, + Used); break; case Type::LValueReference: case Type::RValueReference: - MarkDeducedTemplateParameters(SemaRef, - cast<ReferenceType>(T)->getPointeeType(), - Deduced); + MarkUsedTemplateParameters(SemaRef, + cast<ReferenceType>(T)->getPointeeType(), + OnlyDeduced, + Used); break; case Type::MemberPointer: { const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr()); - MarkDeducedTemplateParameters(SemaRef, MemPtr->getPointeeType(), Deduced); - MarkDeducedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0), - Deduced); + MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced, + Used); + MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0), + OnlyDeduced, Used); break; } case Type::DependentSizedArray: - MarkDeducedTemplateParameters(cast<DependentSizedArrayType>(T)->getSizeExpr(), - Deduced); + MarkUsedTemplateParameters(SemaRef, + cast<DependentSizedArrayType>(T)->getSizeExpr(), + OnlyDeduced, Used); // Fall through to check the element type case Type::ConstantArray: case Type::IncompleteArray: - MarkDeducedTemplateParameters(SemaRef, - cast<ArrayType>(T)->getElementType(), - Deduced); + MarkUsedTemplateParameters(SemaRef, + cast<ArrayType>(T)->getElementType(), + OnlyDeduced, Used); break; case Type::Vector: case Type::ExtVector: - MarkDeducedTemplateParameters(SemaRef, - cast<VectorType>(T)->getElementType(), - Deduced); + MarkUsedTemplateParameters(SemaRef, + cast<VectorType>(T)->getElementType(), + OnlyDeduced, Used); break; case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast<DependentSizedExtVectorType>(T); - MarkDeducedTemplateParameters(SemaRef, VecType->getElementType(), Deduced); - MarkDeducedTemplateParameters(VecType->getSizeExpr(), Deduced); + MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced, + Used); + MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced, + Used); break; } case Type::FunctionProto: { const FunctionProtoType *Proto = cast<FunctionProtoType>(T); - MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced); + MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced, + Used); for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I) - MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced); + MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced, + Used); break; } case Type::TemplateTypeParm: - Deduced[cast<TemplateTypeParmType>(T)->getIndex()] = true; + Used[cast<TemplateTypeParmType>(T)->getIndex()] = true; break; case Type::TemplateSpecialization: { const TemplateSpecializationType *Spec = cast<TemplateSpecializationType>(T); - if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl()) - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Template)) - Deduced[TTP->getIndex()] = true; + MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced, + Used); + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Used); + break; + } - for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) - MarkDeducedTemplateParameters(SemaRef, Spec->getArg(I), Deduced); + case Type::Complex: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<ComplexType>(T)->getElementType(), + OnlyDeduced, Used); + break; + case Type::Typename: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<TypenameType>(T)->getQualifier(), + OnlyDeduced, Used); break; - } - // None of these types have any deducible parts. + // None of these types have any template parameters in them. 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::ObjCObjectPointer: #define TYPE(Class, Base) @@ -2007,32 +2068,39 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, } } -/// \brief Mark the template parameters that are deduced by this +/// \brief Mark the template parameters that are used by this /// template argument. static void -MarkDeducedTemplateParameters(Sema &SemaRef, - const TemplateArgument &TemplateArg, - llvm::SmallVectorImpl<bool> &Deduced) { +MarkUsedTemplateParameters(Sema &SemaRef, + const TemplateArgument &TemplateArg, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used) { switch (TemplateArg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: break; case TemplateArgument::Type: - MarkDeducedTemplateParameters(SemaRef, TemplateArg.getAsType(), Deduced); + MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced, + Used); break; case TemplateArgument::Declaration: if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) - Deduced[TTP->getIndex()] = true; + Used[TTP->getIndex()] = true; break; case TemplateArgument::Expression: - MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced); + MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced, + Used); break; + case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); + for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(), + PEnd = TemplateArg.pack_end(); + P != PEnd; ++P) + MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Used); break; } } @@ -2047,8 +2115,9 @@ MarkDeducedTemplateParameters(Sema &SemaRef, /// to indicate when the corresponding template parameter will be /// deduced. void -Sema::MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs, - llvm::SmallVectorImpl<bool> &Deduced) { +Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, + bool OnlyDeduced, + llvm::SmallVectorImpl<bool> &Used) { for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) - ::MarkDeducedTemplateParameters(*this, TemplateArgs[I], Deduced); + ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, Used); } diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp index a93b541213..072789c7d5 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc -fsyntax-only %s +// RUN: clang-cc -fsyntax-only -verify %s template <class T> T* f(int); // #1 template <class T, class U> T& f(U); // #2 @@ -7,4 +7,16 @@ void g() { int *ip = f<int>(1); // calls #1 } -// FIXME: test occurrences of template parameters in non-deduced contexts. +template<typename T> +struct identity { + typedef T type; +}; + +template <class T> + T* f2(int, typename identity<T>::type = 0); // expected-note{{candidate}} +template <class T, class U> + T& f2(U, typename identity<T>::type = 0); // expected-note{{candidate}} + +void g2() { + f2<int>(1); // expected-error{{ambiguous}} +} |