diff options
| -rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 203 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp | 16 | 
4 files changed, 155 insertions, 72 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0ef20ee9cb0..c0719d4577a 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f8b48b218ab..ab791a468cf 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index d9d1483c67c..0ca7fccd504 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp index a93b541213b..072789c7d57 100644 --- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp +++ b/clang/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}} +}  | 

