aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclTemplate.h10
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def2
-rw-r--r--lib/AST/DeclTemplate.cpp20
-rw-r--r--lib/Sema/SemaTemplate.cpp5
-rw-r--r--test/SemaTemplate/default-arguments.cpp13
-rw-r--r--test/SemaTemplate/temp_arg.cpp2
6 files changed, 49 insertions, 3 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index ccbe1288f8..334a03a439 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -66,9 +66,19 @@ public:
unsigned size() const { return NumParams; }
+ /// \btief Returns the minimum number of arguments needed to form a
+ /// template specialization. This may be fewer than the number of
+ /// template parameters, if some of the parameters have default
+ /// arguments.
+ unsigned getMinRequiredArguments() const;
+
SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TemplateLoc, RAngleLoc);
+ }
};
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def
index 4fed9443d0..25fe8254bb 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/include/clang/Basic/DiagnosticSemaKinds.def
@@ -505,6 +505,8 @@ DIAG(err_template_param_default_arg_missing, ERROR,
// C++ Template Argument Lists
DIAG(err_template_arg_list_different_arity, ERROR,
"%select{too few|too many}0 template arguments for %select{class template|function template|template template parameter|template}1 %2")
+DIAG(note_template_decl_here, NOTE,
+ "template is declared here")
DIAG(err_template_arg_must_be_type, ERROR,
"template argument for template type parameter must be a type")
DIAG(err_template_arg_must_be_expr, ERROR,
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index b297dd25cb..dccb8df075 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -44,6 +44,26 @@ TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc,
NumParams, RAngleLoc);
}
+unsigned TemplateParameterList::getMinRequiredArguments() const {
+ unsigned NumRequiredArgs = size();
+ iterator Param = const_cast<TemplateParameterList *>(this)->end(),
+ ParamBegin = const_cast<TemplateParameterList *>(this)->begin();
+ while (Param != ParamBegin) {
+ --Param;
+ if (!(isa<TemplateTypeParmDecl>(*Param) &&
+ cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
+ !(isa<NonTypeTemplateParmDecl>(*Param) &&
+ cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
+ !(isa<TemplateTemplateParmDecl>(*Param) &&
+ cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument()))
+ break;
+
+ --NumRequiredArgs;
+ }
+
+ return NumRequiredArgs;
+}
+
//===----------------------------------------------------------------------===//
// TemplateDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 86f1e2017f..b4436a2c3c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -685,7 +685,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
bool Invalid = false;
if (NumArgs > NumParams ||
- NumArgs < NumParams /*FIXME: default arguments! */) {
+ NumArgs < Params->getMinRequiredArguments()) {
// FIXME: point at either the first arg beyond what we can handle,
// or the '>', depending on whether we have too many or too few
// arguments.
@@ -698,7 +698,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
isa<FunctionTemplateDecl>(Template)? 1 :
isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
<< Template << Range;
-
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
Invalid = true;
}
diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp
new file mode 100644
index 0000000000..94976e9735
--- /dev/null
+++ b/test/SemaTemplate/default-arguments.cpp
@@ -0,0 +1,13 @@
+// RUN: clang -fsyntax-only -verify %s
+
+template<typename T, int N = 2> struct X; // expected-note{{template is declared here}}
+
+X<int, 1> *x1;
+X<int> *x2;
+
+X<> *x3; // expected-error{{too few template arguments for class template 'X'}} \
+ // FIXME: expected-error{{expected unqualified-id}}
+
+template<typename U = float, int M> struct X;
+
+X<> *x4;
diff --git a/test/SemaTemplate/temp_arg.cpp b/test/SemaTemplate/temp_arg.cpp
index 0f69b5f4b1..b8bb279caf 100644
--- a/test/SemaTemplate/temp_arg.cpp
+++ b/test/SemaTemplate/temp_arg.cpp
@@ -2,7 +2,7 @@
template<typename T,
int I,
template<typename> class TT>
- class A;
+ class A; // expected-note 2 {{template is declared here}}
template<typename> class X;