From 657bad441edaafc88375f9c182cff569b1c81c1d Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 5 Sep 2009 05:14:19 +0000 Subject: [PATCH] Use a separate diagnostic for default function argument expressions. llvm-svn: 81062 --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Sema/Sema.h | 13 ++++++ clang/lib/Sema/SemaExpr.cpp | 9 ++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 43 +++++++++++++++++++ .../SemaTemplate/default-expr-arguments.cpp | 10 ++--- 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ddb82f4319bd..1aa842064983 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -977,6 +977,9 @@ def note_template_static_data_member_def_here : Note< def note_default_arg_instantiation_here : Note< "in instantiation of default argument for '%0' required here">; +def note_default_function_arg_instantiation_here : Note< + "in instantiation of default function argument expression " + "for '%0' required here">; def note_explicit_template_arg_substitution_here : Note< "while substituting explicitly-specified template arguments into function " "template %f, here">; diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 1c118ab64e19..4b9447740add 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2730,6 +2730,11 @@ public: /// FIXME: Use a TemplateArgumentList DefaultTemplateArgumentInstantiation, + /// We are instantiating a default argument for a function. + /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs + /// provides the template arguments as specified. + DefaultFunctionArgumentInstantiation, + /// We are substituting explicit template arguments provided for /// a function template. The entity is a FunctionTemplateDecl. ExplicitTemplateArgumentSubstitution, @@ -2778,7 +2783,9 @@ public: case DefaultTemplateArgumentInstantiation: case ExplicitTemplateArgumentSubstitution: case DeducedTemplateArgumentSubstitution: + case DefaultFunctionArgumentInstantiation: return X.TemplateArgs == Y.TemplateArgs; + } return true; @@ -2852,6 +2859,12 @@ public: unsigned NumTemplateArgs, SourceRange InstantiationRange = SourceRange()); + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ParmVarDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange = SourceRange()); + /// \brief Note that we have finished instantiating this template. void Clear(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 58d6a0dbac7b..7d2e308349f9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2573,12 +2573,9 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // Instantiate the expression. MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD); - - // 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, CallLoc, FD->getPrimaryTemplate(), - ArgList.getInnermost().getFlatArgumentList(), + + InstantiatingTemplate Inst(*this, CallLoc, Param, + ArgList.getInnermost().getFlatArgumentList(), ArgList.getInnermost().flat_size()); OwningExprResult Result = SubstExpr(UninstExpr, ArgList); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 55e81aecbc76..b48708305a36 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -164,6 +164,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, } } +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantation, + ParmVarDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef) { + + Invalid = CheckInstantiationDepth(PointOfInstantation, InstantiationRange); + + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind + = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; + Inst.PointOfInstantiation = PointOfInstantation; + Inst.Entity = reinterpret_cast(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + Invalid = false; + } +} + void Sema::InstantiatingTemplate::Clear() { if (!Invalid) { SemaRef.ActiveTemplateInstantiations.pop_back(); @@ -266,6 +290,23 @@ void Sema::PrintInstantiationStack() { } break; + case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: { + ParmVarDecl *Param = cast((Decl *)Active->Entity); + FunctionDecl *FD = cast(Param->getDeclContext()); + TemplateDecl *Template = FD->getPrimaryTemplate(); + + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + Active->TemplateArgs, + Active->NumTemplateArgs, + Context.PrintingPolicy); + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_default_function_arg_instantiation_here) + << (Template->getNameAsString() + TemplateArgsStr) + << Active->InstantiationRange; + break; + } + } } } @@ -280,6 +321,8 @@ bool Sema::isSFINAEContext() const { switch(Active->Kind) { case ActiveTemplateInstantiation::TemplateInstantiation: + case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: + // This is a template instantiation, so there is no SFINAE. return false; diff --git a/clang/test/SemaTemplate/default-expr-arguments.cpp b/clang/test/SemaTemplate/default-expr-arguments.cpp index 7e705b034d45..5c95e511a7fa 100644 --- a/clang/test/SemaTemplate/default-expr-arguments.cpp +++ b/clang/test/SemaTemplate/default-expr-arguments.cpp @@ -10,28 +10,28 @@ template void f3(T a, T b = T() + T()); // expected-error{{invalid o void g() { f1(10); - f1(S()); // expected-note{{in instantiation of default argument for 'f1' required here}} + f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1' required here}} f2(10); f2(S()); f3(10); - f3(S()); // expected-note{{in instantiation of default argument for 'f3' required here}} + f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3' required here}} } template struct F { - F(T t = 10); + F(T t = 10); }; struct FD : F { }; void g2() { - F f; + F f; FD fd; } template struct G { - G(T) {} + G(T) {} }; void s(G flags = 10) { }