diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 89 |
1 files changed, 52 insertions, 37 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 19c0f2a..f4740a5 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -602,7 +602,7 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, return Param; } - Param->setDefaultArgument(DefaultTInfo, false); + Param->setDefaultArgument(DefaultTInfo); } return Param; @@ -723,7 +723,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, } Default = DefaultRes.get(); - Param->setDefaultArgument(Default, false); + Param->setDefaultArgument(Default); } return Param; @@ -799,7 +799,7 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, UPPC_DefaultArgument)) return Param; - Param->setDefaultArgument(DefaultArg, false); + Param->setDefaultArgument(Context, DefaultArg); } return Param; @@ -1310,15 +1310,11 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for template type parameters. TemplateTypeParmDecl *OldTypeParm = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr; - // FIXME: There might be a visible declaration of this template parameter. - if (OldTypeParm && !LookupResult::isVisible(*this, OldTypeParm)) - OldTypeParm = nullptr; - if (NewTypeParm->isParameterPack()) { assert(!NewTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); SawParameterPack = true; - } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && + } else if (OldTypeParm && hasVisibleDefaultArgument(OldTypeParm) && NewTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc(); @@ -1328,8 +1324,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(), - true); + NewTypeParm->setInheritedDefaultArgument(Context, OldTypeParm); PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc(); } else if (NewTypeParm->hasDefaultArgument()) { SawDefaultArgument = true; @@ -1358,14 +1353,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for non-type template parameters NonTypeTemplateParmDecl *OldNonTypeParm = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr; - if (OldNonTypeParm && !LookupResult::isVisible(*this, OldNonTypeParm)) - OldNonTypeParm = nullptr; if (NewNonTypeParm->isParameterPack()) { assert(!NewNonTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); if (!NewNonTypeParm->isPackExpansion()) SawParameterPack = true; - } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && + } else if (OldNonTypeParm && hasVisibleDefaultArgument(OldNonTypeParm) && NewNonTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); @@ -1375,12 +1368,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - // FIXME: We need to create a new kind of "default argument" - // expression that points to a previous non-type template - // parameter. - NewNonTypeParm->setDefaultArgument( - OldNonTypeParm->getDefaultArgument(), - /*Inherited=*/ true); + NewNonTypeParm->setInheritedDefaultArgument(Context, OldNonTypeParm); PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc(); } else if (NewNonTypeParm->hasDefaultArgument()) { SawDefaultArgument = true; @@ -1407,15 +1395,14 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for template template parameters TemplateTemplateParmDecl *OldTemplateParm = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr; - if (OldTemplateParm && !LookupResult::isVisible(*this, OldTemplateParm)) - OldTemplateParm = nullptr; if (NewTemplateParm->isParameterPack()) { assert(!NewTemplateParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); if (!NewTemplateParm->isPackExpansion()) SawParameterPack = true; - } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && - NewTemplateParm->hasDefaultArgument()) { + } else if (OldTemplateParm && + hasVisibleDefaultArgument(OldTemplateParm) && + NewTemplateParm->hasDefaultArgument()) { OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); SawDefaultArgument = true; @@ -1424,11 +1411,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - // FIXME: We need to create a new kind of "default argument" expression - // that points to a previous template template parameter. - NewTemplateParm->setDefaultArgument( - OldTemplateParm->getDefaultArgument(), - /*Inherited=*/ true); + NewTemplateParm->setInheritedDefaultArgument(Context, OldTemplateParm); PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgument().getLocation(); } else if (NewTemplateParm->hasDefaultArgument()) { @@ -3316,7 +3299,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, HasDefaultArg = false; if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { - if (!TypeParm->hasDefaultArgument()) + if (!hasVisibleDefaultArgument(TypeParm)) return TemplateArgumentLoc(); HasDefaultArg = true; @@ -3333,7 +3316,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (NonTypeTemplateParmDecl *NonTypeParm = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (!NonTypeParm->hasDefaultArgument()) + if (!hasVisibleDefaultArgument(NonTypeParm)) return TemplateArgumentLoc(); HasDefaultArg = true; @@ -3351,7 +3334,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, TemplateTemplateParmDecl *TempTempParm = cast<TemplateTemplateParmDecl>(Param); - if (!TempTempParm->hasDefaultArgument()) + if (!hasVisibleDefaultArgument(TempTempParm)) return TemplateArgumentLoc(); HasDefaultArg = true; @@ -3661,6 +3644,35 @@ static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) { return None; } +/// Diagnose a missing template argument. +template<typename TemplateParmDecl> +static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, + TemplateDecl *TD, + const TemplateParmDecl *D, + TemplateArgumentListInfo &Args) { + // Dig out the most recent declaration of the template parameter; there may be + // declarations of the template that are more recent than TD. + D = cast<TemplateParmDecl>(cast<TemplateDecl>(TD->getMostRecentDecl()) + ->getTemplateParameters() + ->getParam(D->getIndex())); + + // If there's a default argument that's not visible, diagnose that we're + // missing a module import. + llvm::SmallVector<Module*, 8> Modules; + if (D->hasDefaultArgument() && !S.hasVisibleDefaultArgument(D, &Modules)) { + S.diagnoseMissingImport(Loc, cast<NamedDecl>(TD), + D->getDefaultArgumentLoc(), Modules, + Sema::MissingImportKind::DefaultArgument, + /*Recover*/ true); + return true; + } + + // FIXME: If there's a more recent default argument that *is* visible, + // diagnose that it was declared too late. + + return diagnoseArityMismatch(S, TD, Loc, Args); +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, @@ -3816,8 +3828,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // (when the template parameter was part of a nested template) into // the default argument. if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { - if (!TTP->hasDefaultArgument()) - return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs); + if (!hasVisibleDefaultArgument(TTP)) + return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, + NewArgs); TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this, Template, @@ -3832,8 +3845,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (!NTTP->hasDefaultArgument()) - return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs); + if (!hasVisibleDefaultArgument(NTTP)) + return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, + NewArgs); ExprResult E = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, @@ -3849,8 +3863,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - if (!TempParm->hasDefaultArgument()) - return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs); + if (!hasVisibleDefaultArgument(TempParm)) + return diagnoseMissingArgument(*this, TemplateLoc, Template, TempParm, + NewArgs); NestedNameSpecifierLoc QualifierLoc; TemplateName Name = SubstDefaultTemplateArgument(*this, Template, |