[cfe-commits] r89874 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp test/Parser/cxx-template-decl.cpp test/SemaTemplate/default-arguments-cxx0x.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 25 10:55:14 PST 2009


Author: dgregor
Date: Wed Nov 25 12:55:14 2009
New Revision: 89874

URL: http://llvm.org/viewvc/llvm-project?rev=89874&view=rev
Log:
Implement support for default template arguments of function templates.

Added:
    cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/test/Parser/cxx-template-decl.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=89874&r1=89873&r2=89874&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Nov 25 12:55:14 2009
@@ -882,7 +882,7 @@
 def err_template_param_shadow : Error<
   "declaration of %0 shadows template parameter">;
 def note_template_param_here : Note<"template parameter is declared here">;
-def note_template_export_unsupported : Note<
+def warn_template_export_unsupported : Warning<
   "exported templates are unsupported">;
 def err_template_outside_namespace_or_class_scope : Error<
   "templates can only be declared in namespace or class scope">;

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 25 12:55:14 2009
@@ -2384,6 +2384,13 @@
                                                 SourceLocation TemplateLoc,
                                                 Declarator &D);
     
+  TemplateArgumentLoc 
+  SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+                                          SourceLocation TemplateLoc,
+                                          SourceLocation RAngleLoc,
+                                          Decl *Param,
+                                      TemplateArgumentListBuilder &Converted);
+
   bool CheckTemplateArgument(NamedDecl *Param,
                              const TemplateArgumentLoc &Arg,
                              TemplateDecl *Template,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov 25 12:55:14 2009
@@ -764,7 +764,7 @@
                                  DeclPtrTy *Params, unsigned NumParams,
                                  SourceLocation RAngleLoc) {
   if (ExportLoc.isValid())
-    Diag(ExportLoc, diag::note_template_export_unsupported);
+    Diag(ExportLoc, diag::warn_template_export_unsupported);
 
   return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
                                        (NamedDecl**)Params, NumParams, 
@@ -1869,6 +1869,65 @@
                                    AllTemplateArgs);
 }
 
+/// \brief If the given template parameter has a default template
+/// argument, substitute into that default template argument and
+/// return the corresponding template argument.
+TemplateArgumentLoc 
+Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+                                              SourceLocation TemplateLoc,
+                                              SourceLocation RAngleLoc,
+                                              Decl *Param,
+                                     TemplateArgumentListBuilder &Converted) {
+  if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
+    if (!TypeParm->hasDefaultArgument())
+      return TemplateArgumentLoc();
+
+    DeclaratorInfo *DI = SubstDefaultTemplateArgument(*this, Template,
+                                                      TemplateLoc,
+                                                      RAngleLoc,
+                                                      TypeParm,
+                                                      Converted);
+    if (DI)
+      return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+
+    return TemplateArgumentLoc();
+  }
+
+  if (NonTypeTemplateParmDecl *NonTypeParm
+        = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+    if (!NonTypeParm->hasDefaultArgument())
+      return TemplateArgumentLoc();
+
+    OwningExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
+                                                        TemplateLoc,
+                                                        RAngleLoc,
+                                                        NonTypeParm,
+                                                        Converted);
+    if (Arg.isInvalid())
+      return TemplateArgumentLoc();
+
+    Expr *ArgE = Arg.takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
+  }
+
+  TemplateTemplateParmDecl *TempTempParm
+    = cast<TemplateTemplateParmDecl>(Param);
+  if (!TempTempParm->hasDefaultArgument())
+    return TemplateArgumentLoc();
+
+  TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
+                                                    TemplateLoc, 
+                                                    RAngleLoc,
+                                                    TempTempParm,
+                                                    Converted);
+  if (TName.isNull())
+    return TemplateArgumentLoc();
+
+  return TemplateArgumentLoc(TemplateArgument(TName), 
+                TempTempParm->getDefaultArgument().getTemplateQualifierRange(),
+                TempTempParm->getDefaultArgument().getTemplateNameLoc());
+}
+
 /// \brief Check that the given template argument corresponds to the given
 /// template parameter.
 bool Sema::CheckTemplateArgument(NamedDecl *Param,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Nov 25 12:55:14 2009
@@ -1272,18 +1272,56 @@
   TemplateParameterList *TemplateParams
     = FunctionTemplate->getTemplateParameters();
 
+  // Template argument deduction for function templates in a SFINAE context.
+  // Trap any errors that might occur.
+  SFINAETrap Trap(*this);
+
+  // Enter a new template instantiation context while we instantiate the
+  // actual function declaration.
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+                             FunctionTemplate, Deduced.data(), Deduced.size(),
+              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
   // C++ [temp.deduct.type]p2:
   //   [...] or if any template argument remains neither deduced nor
   //   explicitly specified, template argument deduction fails.
   TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
   for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
-    if (Deduced[I].isNull()) {
+    if (!Deduced[I].isNull()) {
+      Builder.Append(Deduced[I]);
+      continue;
+    }
+
+    // Substitute into the default template argument, if available. 
+    NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I);
+    TemplateArgumentLoc DefArg
+      = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
+                                              FunctionTemplate->getLocation(),
+                                  FunctionTemplate->getSourceRange().getEnd(),
+                                                Param,
+                                                Builder);
+
+    // If there was no default argument, deduction is incomplete.
+    if (DefArg.getArgument().isNull()) {
       Info.Param = makeTemplateParameter(
-                            const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
       return TDK_Incomplete;
     }
+    
+    // Check whether we can actually use the default argument.
+    if (CheckTemplateArgument(Param, DefArg,
+                              FunctionTemplate,
+                              FunctionTemplate->getLocation(),
+                              FunctionTemplate->getSourceRange().getEnd(),
+                              Builder)) {
+      Info.Param = makeTemplateParameter(
+                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      return TDK_SubstitutionFailure;
+    }
 
-    Builder.Append(Deduced[I]);
+    // If we get here, we successfully used the default template argument.
   }
 
   // Form the template argument list from the deduced template arguments.
@@ -1291,18 +1329,6 @@
     = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
   Info.reset(DeducedArgumentList);
 
-  // Template argument deduction for function templates in a SFINAE context.
-  // Trap any errors that might occur.
-  SFINAETrap Trap(*this);
-
-  // Enter a new template instantiation context while we instantiate the
-  // actual function declaration.
-  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
-                             FunctionTemplate, Deduced.data(), Deduced.size(),
-              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
-  if (Inst)
-    return TDK_InstantiationDepth;
-
   // Substitute the deduced template arguments into the function template
   // declaration to produce the function template specialization.
   Specialization = cast_or_null<FunctionDecl>(

Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=89874&r1=89873&r2=89874&view=diff

==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Wed Nov 25 12:55:14 2009
@@ -5,7 +5,7 @@
 template  x;            // expected-error {{C++ requires a type specifier for all declarations}} \
                         // expected-error {{does not refer}}
 export template x;      // expected-error {{expected '<' after 'template'}}
-export template<class T> class x0; // expected-note {{exported templates are unsupported}}
+export template<class T> class x0; // expected-warning {{exported templates are unsupported}}
 template < ;            // expected-error {{parse error}} expected-error {{declaration does not declare anything}}
 template <template X> struct Err1; // expected-error {{expected '<' after 'template'}} \
 // expected-error{{extraneous}}

Added: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp?rev=89874&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp (added)
+++ cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp Wed Nov 25 12:55:14 2009
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
+
+// Test default template arguments for function templates.
+template<typename T = int>
+void f0();
+
+template<typename T>
+void f0();
+
+void g0() {
+  f0(); // okay!
+} 
+
+template<typename T, int N = T::value>
+int &f1(T);
+
+float &f1(...);
+
+struct HasValue {
+  static const int value = 17;
+};
+
+void g1() {
+  float &fr = f1(15);
+  int &ir = f1(HasValue());
+}

Propchange: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list