]> granicus.if.org Git - clang/commitdiff
Basic support for default argument expressions for function templates.
authorAnders Carlsson <andersca@mac.com>
Tue, 25 Aug 2009 03:18:48 +0000 (03:18 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 25 Aug 2009 03:18:48 +0000 (03:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79972 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/default-expr-arguments.cpp [new file with mode: 0644]

index 5452963fad00cb4ae6841ed93fa551b8b3ef1bf1..0ddf8b0a7754128e83f9e250ae3ecfe8e2b5e3b6 100644 (file)
@@ -117,7 +117,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
   //   copy-initialization semantics (8.5).
   if (CheckInitializerTypes(Arg, ParamType, EqualLoc, 
                             Param->getDeclName(), /*DirectInit=*/false))
-    return false;
+    return true;
 
   Arg = MaybeCreateCXXExprWithTemporaries(Arg, /*DestroyTemps=*/false);
   
@@ -126,7 +126,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
   
   DefaultArg.release();
   
-  return true;
+  return false;
 }
 
 /// ActOnParamDefaultArgument - Check whether the default argument
index 04a15054430a6bfa2a60ae2e799fc8b648bcd239..013273cd8c001e4df2d3800c6eca4c693ca8e354 100644 (file)
@@ -2500,6 +2500,33 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
         Diag(UnparsedDefaultArgLocs[Param], 
               diag::note_default_argument_declared_here);
       } else {
+        if (Param->hasUninstantiatedDefaultArg()) {
+          Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
+
+          // Instantiate the expression.
+          const TemplateArgumentList &ArgList = 
+            getTemplateInstantiationArgs(FDecl);
+          
+          // FIXME: We should really make a new InstantiatingTemplate ctor
+          // that has a better message - right now we're just piggy-backing 
+          // off the "default template argument" error message.
+          InstantiatingTemplate Inst(*this, Call->getSourceRange().getBegin(),
+                                     FDecl->getPrimaryTemplate(),
+                                     ArgList.getFlatArgumentList(),
+                                     ArgList.flat_size());
+
+          OwningExprResult Result
+            = InstantiateExpr(UninstExpr, 
+                              getTemplateInstantiationArgs(FDecl));
+          if (Result.isInvalid()) 
+            return true;
+          
+          if (SetParamDefaultArgument(Param, move(Result), 
+                                      /*FIXME:EqualLoc*/
+                                      UninstExpr->getSourceRange().getBegin()))
+            return true;
+        }
+        
         Expr *DefaultExpr = Param->getDefaultArg();
         
         // If the default expression creates temporaries, we need to
index ded49b33ab18c15c43482831cb145f1518c792fc..86b1cbdf9d1fd33c27d87b3c5fd14c85e2811aa5 100644 (file)
@@ -591,16 +591,6 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
 
   QualType T = SemaRef.adjustParameterType(OrigT);
 
-  if (D->getDefaultArg()) {
-    // FIXME: Leave a marker for "uninstantiated" default
-    // arguments. They only get instantiated on demand at the call
-    // site.
-    unsigned DiagID = SemaRef.Diags.getCustomDiagID(Diagnostic::Warning,
-        "sorry, dropping default argument during template instantiation");
-    SemaRef.Diag(D->getDefaultArg()->getSourceRange().getBegin(), DiagID)
-      << D->getDefaultArg()->getSourceRange();
-  }
-
   // Allocate the parameter
   ParmVarDecl *Param = 0;
   if (T == OrigT)
@@ -613,6 +603,10 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
                                         T, D->getDeclaratorInfo(), OrigT,
                                         D->getStorageClass(), 0);
 
+  // Mark the default argument as being uninstantiated.
+  if (Expr *Arg = D->getDefaultArg())
+    Param->setUninstantiatedDefaultArg(Arg);
+  
   // Note: we don't try to instantiate function parameters until after
   // we've instantiated the function's type. Therefore, we don't have
   // to check for 'void' parameter types here.
diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp
new file mode 100644 (file)
index 0000000..87532ef
--- /dev/null
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct S { };
+
+template<typename T> void f1(T a, T b = 10) { } // expected-error{{cannot initialize 'b' with an rvalue of type 'int'}}
+
+template<typename T> void f2(T a, T b = T()) { }
+
+template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid operands to binary expression ('struct S' and 'struct S')}}
+
+void g() {
+  f1(10);
+  f1(S()); // expected-note{{in instantiation of default argument for 'f1<struct S>' required here}}
+  
+  f2(10);
+  f2(S());
+  
+  f3(10);
+  f3(S()); // expected-note{{in instantiation of default argument for 'f3<struct S>' required here}}
+}