[cfe-commits] r81794 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp

Douglas Gregor dgregor at apple.com
Mon Sep 14 14:25:05 PDT 2009


Author: dgregor
Date: Mon Sep 14 16:25:05 2009
New Revision: 81794

URL: http://llvm.org/viewvc/llvm-project?rev=81794&view=rev
Log:
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.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=81794&r1=81793&r2=81794&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Sep 14 16:25:05 2009
@@ -2732,8 +2732,9 @@
                                                    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

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=81794&r1=81793&r2=81794&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Sep 14 16:25:05 2009
@@ -2720,7 +2720,8 @@
     // 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])

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=81794&r1=81793&r2=81794&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Sep 14 16:25:05 2009
@@ -1677,8 +1677,9 @@
 }
 
 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 @@
     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 @@
 }
 
 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 @@
   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 @@
   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 @@
   }
 }
 
-/// \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 @@
 /// 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);
 }

Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp?rev=81794&r1=81793&r2=81794&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp Mon Sep 14 16:25:05 2009
@@ -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 @@
   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}}
+}





More information about the cfe-commits mailing list