diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 13 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 43 | ||||
-rw-r--r-- | test/SemaTemplate/default-expr-arguments.cpp | 10 |
5 files changed, 67 insertions, 11 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ddb82f4319..1aa8420649 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1c118ab64e..4b9447740a 100644 --- a/lib/Sema/Sema.h +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 58d6a0dbac..7d2e308349 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 55e81aecbc..b48708305a 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/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<uintptr_t>(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<ParmVarDecl>((Decl *)Active->Entity); + FunctionDecl *FD = cast<FunctionDecl>(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/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp index 7e705b034d..5c95e511a7 100644 --- a/test/SemaTemplate/default-expr-arguments.cpp +++ b/test/SemaTemplate/default-expr-arguments.cpp @@ -10,28 +10,28 @@ template<typename T> 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<struct S>' required here}} + f1(S()); // expected-note{{in instantiation of default function argument expression 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}} + f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<struct S>' required here}} } template<typename T> struct F { - F(T t = 10); + F(T t = 10); }; struct FD : F<int> { }; void g2() { - F<int> f; + F<int> f; FD fd; } template<typename T> struct G { - G(T) {} + G(T) {} }; void s(G<int> flags = 10) { } |