From e30bd8a0b6ed0b6e77b98a8cb367dcdaa3c8d6a3 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Fri, 31 Jan 2025 17:51:18 -0300 Subject: [PATCH] [clang] Implement evaluation context for checking template parameters Instead of manually adding a note pointing to the relevant template parameter to every relevant error, which is very easy to miss, this patch adds a new instantiation context note, so that this can work using RAII magic. This fixes a bunch of places where these notes were missing, and is more future-proof. Some diagnostics are reworked to make better use of this note: - Errors about missing template arguments now refer to the parameter which is missing an argument. - Template Template parameter mismatches now refer to template parameters as parameters instead of arguments. It's likely this will add the note to some diagnostics where the parameter is not super relevant, but this can be reworked with time and the decrease in maintenance burden makes up for it. This bypasses the templight dumper for the new context entry, as the tests are very hard to update. This depends on #125453, which is needed to avoid losing the context note for errors occuring during template argument deduction. --- clang/docs/ReleaseNotes.rst | 10 + .../clang/Basic/DiagnosticSemaKinds.td | 27 +-- clang/include/clang/Sema/Sema.h | 37 ++- clang/lib/Frontend/FrontendActions.cpp | 24 +- clang/lib/Sema/SemaInit.cpp | 7 +- clang/lib/Sema/SemaLambda.cpp | 7 +- clang/lib/Sema/SemaLookup.cpp | 14 +- clang/lib/Sema/SemaTemplate.cpp | 221 ++++++------------ clang/lib/Sema/SemaTemplateDeduction.cpp | 4 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 30 ++- clang/test/AST/ByteCode/cxx1z.cpp | 2 +- clang/test/AST/ByteCode/cxx20.cpp | 2 +- clang/test/AST/ByteCode/cxx98.cpp | 2 +- clang/test/AST/ByteCode/records.cpp | 6 +- .../basic.lookup/basic.lookup.unqual/p7.cpp | 1 + .../dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp | 2 +- clang/test/CXX/drs/cwg0xx.cpp | 31 ++- clang/test/CXX/drs/cwg10xx.cpp | 1 + clang/test/CXX/drs/cwg13xx.cpp | 1 + clang/test/CXX/drs/cwg18xx.cpp | 19 +- clang/test/CXX/drs/cwg1xx.cpp | 16 +- clang/test/CXX/drs/cwg20xx.cpp | 10 +- clang/test/CXX/drs/cwg21xx.cpp | 3 +- clang/test/CXX/drs/cwg3xx.cpp | 12 +- clang/test/CXX/drs/cwg4xx.cpp | 17 +- clang/test/CXX/drs/cwg6xx.cpp | 7 +- clang/test/CXX/expr/expr.const/p3-0x.cpp | 7 +- .../expr.prim.req/type-requirement.cpp | 2 +- .../temp/temp.arg/temp.arg.nontype/p1-11.cpp | 2 +- .../CXX/temp/temp.arg/temp.arg.nontype/p1.cpp | 7 +- .../CXX/temp/temp.arg/temp.arg.nontype/p5.cpp | 14 +- .../temp/temp.arg/temp.arg.template/p3-0x.cpp | 20 +- .../temp/temp.arg/temp.arg.template/p3-2a.cpp | 8 +- .../CXX/temp/temp.arg/temp.arg.type/p2.cpp | 18 +- .../temp/temp.decls/temp.class.spec/p8-1y.cpp | 4 +- .../temp.variadic/fixed-expansion.cpp | 42 ++-- .../multi-level-substitution.cpp | 10 +- clang/test/CXX/temp/temp.deduct/p9.cpp | 5 +- clang/test/CXX/temp/temp.param/p1.cpp | 9 +- clang/test/CXX/temp/temp.param/p12.cpp | 4 +- clang/test/CXX/temp/temp.param/p15-cxx0x.cpp | 10 +- clang/test/CXX/temp/temp.param/p8-cxx20.cpp | 2 +- .../temp.dep/temp.dep.constexpr/p2.cpp | 2 +- .../cxx1y-variable-template-no-body.cpp | 10 +- clang/test/CXX/temp/temp.spec/part.spec.cpp | 4 +- .../CXX/temp/temp.spec/temp.expl.spec/p20.cpp | 8 +- clang/test/Misc/integer-literal-printing.cpp | 7 + ...constraint-template-non-type-parm-decl.cpp | 2 +- clang/test/Modules/missing-body-in-import.cpp | 1 + clang/test/Modules/template-default-args.cpp | 4 +- clang/test/Parser/MicrosoftExtensions.cpp | 2 +- clang/test/Parser/cxx-template-argument.cpp | 12 +- .../Parser/cxx-template-template-recovery.cpp | 24 +- ...xx1z-class-template-argument-deduction.cpp | 10 +- clang/test/SemaCXX/access-base-class.cpp | 24 +- clang/test/SemaCXX/alias-template.cpp | 5 +- clang/test/SemaCXX/anonymous-struct.cpp | 3 +- .../SemaCXX/constant-expression-cxx11.cpp | 4 +- clang/test/SemaCXX/constant-expression.cpp | 2 +- .../SemaCXX/cxx1z-noexcept-function-type.cpp | 1 + clang/test/SemaCXX/cxx2a-consteval.cpp | 2 +- clang/test/SemaCXX/cxx98-compat-flags.cpp | 3 +- clang/test/SemaCXX/cxx98-compat.cpp | 11 +- .../SemaCXX/implicit-member-functions.cpp | 1 + clang/test/SemaCXX/lambda-expressions.cpp | 6 +- clang/test/SemaCXX/make_integer_seq.cpp | 3 +- clang/test/SemaCXX/type-trait-common-type.cpp | 6 +- clang/test/SemaCXX/undefined-internal.cpp | 6 +- ...ated-specializations-in-system-headers.cpp | 1 + clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl | 4 +- .../SemaHLSL/BuiltIns/StructuredBuffers.hlsl | 62 ++--- .../SemaObjCXX/parameterized_classes_subst.mm | 2 +- clang/test/SemaTemplate/alias-templates.cpp | 9 +- clang/test/SemaTemplate/cwg2398.cpp | 40 ++-- clang/test/SemaTemplate/default-arguments.cpp | 25 +- .../instantiate-member-pointers.cpp | 12 +- .../instantiate-template-template-parm.cpp | 6 +- .../SemaTemplate/instantiation-default-1.cpp | 13 +- .../SemaTemplate/instantiation-default-2.cpp | 3 +- .../SemaTemplate/instantiation-dependence.cpp | 3 +- .../instantiation-depth-defarg.cpp | 8 +- .../instantiation-depth-exception-spec.cpp | 8 +- .../test/SemaTemplate/instantiation-depth.cpp | 6 +- .../ms-unqualified-base-class.cpp | 4 +- clang/test/SemaTemplate/nested-template.cpp | 6 +- .../SemaTemplate/partial-spec-instantiate.cpp | 3 +- clang/test/SemaTemplate/recovery-crash.cpp | 3 +- clang/test/SemaTemplate/stack-exhaustion.cpp | 8 +- clang/test/SemaTemplate/temp_arg.cpp | 12 +- clang/test/SemaTemplate/temp_arg_nontype.cpp | 20 +- .../SemaTemplate/temp_arg_nontype_cxx11.cpp | 2 +- .../SemaTemplate/temp_arg_nontype_cxx1z.cpp | 8 +- .../SemaTemplate/temp_arg_nontype_cxx20.cpp | 24 +- .../SemaTemplate/temp_arg_nontype_cxx2c.cpp | 10 +- clang/test/SemaTemplate/temp_arg_template.cpp | 25 +- .../SemaTemplate/temp_arg_template_p0522.cpp | 49 ++-- clang/test/SemaTemplate/temp_arg_type.cpp | 7 +- 97 files changed, 648 insertions(+), 575 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 307edf77ebb58..03c3ff87604f2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -236,6 +236,16 @@ Bug Fixes to C++ Support direct-list-initialized from an array is corrected to direct-initialization. - Clang no longer crashes when a coroutine is declared ``[[noreturn]]``. (#GH127327) +Improvements to C++ diagnostics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Clang now more consistently adds a note pointing to the relevant template + parameter. Some diagnostics are reworded to better take advantage of this. +- Template Template Parameter diagnostics now stop referring to template + parameters as template arguments, in some circumstances, better hiding + from the users template template parameter partial ordering arcana. + + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed type checking when a statement expression ends in an l-value of atomic type. (#GH106576) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 73b00752e6b40..177b8d98db8d2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5193,16 +5193,11 @@ def err_template_unnamed_class : Error< def err_template_param_list_different_arity : Error< "%select{too few|too many}0 template parameters in template " "%select{|template parameter }1redeclaration">; -def note_template_param_list_different_arity : Note< - "%select{too few|too many}0 template parameters in template template " - "argument">; def note_template_prev_declaration : Note< "previous template %select{declaration|template parameter}0 is here">; def err_template_param_different_kind : Error< "template parameter has a different kind in template " "%select{|template parameter }0redeclaration">; -def note_template_param_different_kind : Note< - "template parameter has a different kind in template argument">; def err_invalid_decl_specifier_in_nontype_parm : Error< "invalid declaration specifier in template non-type parameter">; @@ -5211,8 +5206,6 @@ def err_template_nontype_parm_different_type : Error< "template non-type parameter has a different type %0 in template " "%select{|template parameter }1redeclaration">; -def note_template_nontype_parm_different_type : Note< - "template non-type parameter has a different type %0 in template argument">; def note_template_nontype_parm_prev_declaration : Note< "previous non-type template parameter with type %0 is here">; def err_template_nontype_parm_bad_type : Error< @@ -5303,10 +5296,15 @@ def err_template_missing_args : Error< "%select{class template|function template|variable template|alias template|" "template template parameter|concept|template}0 %1 requires template " "arguments">; -def err_template_arg_list_different_arity : Error< - "%select{too few|too many}0 template arguments for " +def err_template_param_missing_arg : Error< + "missing template argument for template parameter">; +def err_template_template_param_missing_param : Error< + "no template parameter in this template template parameter " + "corresponds to non-defaulted template parameter of argument template">; +def err_template_too_many_args : Error< + "too many template arguments for " "%select{class template|function template|variable template|alias template|" - "template template parameter|concept|template}1 %2">; + "template template parameter|concept|template}0 %1">; def note_template_decl_here : Note<"template is declared here">; def note_template_decl_external : Note< "template declaration from hidden source: %0">; @@ -5344,11 +5342,8 @@ def err_template_arg_not_valid_template : Error< "template parameter">; def note_template_arg_refers_here_func : Note< "template argument refers to function template %0, here">; -def err_template_arg_template_params_mismatch : Error< - "template template argument has different template parameters than its " - "corresponding template template parameter">; def note_template_arg_template_params_mismatch : Note< - "template template argument has different template parameters than its " + "template template argument is incompatible with its " "corresponding template template parameter">; def err_non_deduced_mismatch : Error< "could not match %diff{$ against $|types}0,1">; @@ -5910,10 +5905,6 @@ def err_template_parameter_pack_non_pack : Error< "%select{template type|non-type template|template template}0 parameter" "%select{| pack}1 conflicts with previous %select{template type|" "non-type template|template template}0 parameter%select{ pack|}1">; -def note_template_parameter_pack_non_pack : Note< - "%select{template type|non-type template|template template}0 parameter" - "%select{| pack}1 does not match %select{template type|non-type template" - "|template template}0 parameter%select{ pack|}1 in template argument">; def note_template_parameter_pack_here : Note< "previous %select{template type|non-type template|template template}0 " "parameter%select{| pack}1 declared here">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ebdbc69384efb..53d17936673ce 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11820,7 +11820,7 @@ class Sema final : public SemaBase { bool *ConstraintsNotSatisfied = nullptr); bool CheckTemplateTypeArgument( - TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, + TemplateArgumentLoc &Arg, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted); @@ -11856,9 +11856,13 @@ class Sema final : public SemaBase { bool PartialOrdering, bool *StrictPackMatch); + /// Print the given named declaration to a string, + /// using the current PrintingPolicy, except that + /// TerseOutput will always be set. + SmallString<128> toTerseString(const NamedDecl &D) const; + void NoteTemplateLocation(const NamedDecl &Decl, std::optional ParamRange = {}); - void NoteTemplateParameterLocation(const NamedDecl &Decl); /// Given a non-type template argument that refers to a /// declaration and the type of its corresponding non-type template @@ -11973,15 +11977,13 @@ class Sema final : public SemaBase { bool TemplateParameterListsAreEqual( const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, - TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc = SourceLocation()); + TemplateParameterListEqualKind Kind); - bool TemplateParameterListsAreEqual( - TemplateParameterList *New, TemplateParameterList *Old, bool Complain, - TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc = SourceLocation()) { + bool TemplateParameterListsAreEqual(TemplateParameterList *New, + TemplateParameterList *Old, bool Complain, + TemplateParameterListEqualKind Kind) { return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain, - Kind, TemplateArgLoc); + Kind); } /// Check whether a template can be declared within this scope. @@ -12860,6 +12862,11 @@ class Sema final : public SemaBase { /// We are performing partial ordering for template template parameters. PartialOrderingTTP, + + /// We are Checking a Template Parameter, so for any diagnostics which + /// occur in this scope, we will add a context note which points to this + /// template parameter. + CheckTemplateParameter, } Kind; /// Was the enclosing context a non-instantiation SFINAE context? @@ -13087,6 +13094,11 @@ class Sema final : public SemaBase { PartialOrderingTTP, TemplateDecl *PArg, SourceRange InstantiationRange = SourceRange()); + struct CheckTemplateParameter {}; + /// \brief Note that we are checking a template parameter. + InstantiatingTemplate(Sema &SemaRef, CheckTemplateParameter, + NamedDecl *Param); + /// Note that we have finished instantiating this template. void Clear(); @@ -13120,6 +13132,13 @@ class Sema final : public SemaBase { InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete; }; + /// For any diagnostics which occur within its scope, adds a context note + /// pointing to the declaration of the template parameter. + struct CheckTemplateParameterRAII : InstantiatingTemplate { + CheckTemplateParameterRAII(Sema &S, NamedDecl *Param) + : InstantiatingTemplate(S, CheckTemplateParameter(), Param) {} + }; + bool SubstTemplateArgument(const TemplateArgumentLoc &Input, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentLoc &Output, diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 1ea4a2e9e88cf..60e103e643e27 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -403,7 +403,8 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback { } private: - static std::string toString(CodeSynthesisContext::SynthesisKind Kind) { + static std::optional + toString(CodeSynthesisContext::SynthesisKind Kind) { switch (Kind) { case CodeSynthesisContext::TemplateInstantiation: return "TemplateInstantiation"; @@ -461,8 +462,10 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback { return "TypeAliasTemplateInstantiation"; case CodeSynthesisContext::PartialOrderingTTP: return "PartialOrderingTTP"; + case CodeSynthesisContext::CheckTemplateParameter: + return std::nullopt; } - return ""; + return std::nullopt; } template @@ -470,12 +473,14 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback { const CodeSynthesisContext &Inst) { std::string YAML; { + std::optional Entry = + getTemplightEntry(TheSema, Inst); + if (!Entry) + return; llvm::raw_string_ostream OS(YAML); llvm::yaml::Output YO(OS); - TemplightEntry Entry = - getTemplightEntry(TheSema, Inst); llvm::yaml::EmptyContext Context; - llvm::yaml::yamlize(YO, Entry, true, Context); + llvm::yaml::yamlize(YO, *Entry, true, Context); } Out << "---" << YAML << "\n"; } @@ -555,10 +560,13 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback { } template - static TemplightEntry getTemplightEntry(const Sema &TheSema, - const CodeSynthesisContext &Inst) { + static std::optional + getTemplightEntry(const Sema &TheSema, const CodeSynthesisContext &Inst) { TemplightEntry Entry; - Entry.Kind = toString(Inst.Kind); + std::optional Kind = toString(Inst.Kind); + if (!Kind) + return std::nullopt; + Entry.Kind = *Kind; Entry.Event = BeginInstantiation ? "Begin" : "End"; llvm::raw_string_ostream OS(Entry.Name); printEntryName(TheSema, Inst.Entity, OS); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 925af06894f72..a8c5947f65a87 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -7269,7 +7269,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, void InitializationSequence::PrintInitLocationNote(Sema &S, const InitializedEntity &Entity) { - if (Entity.isParamOrTemplateParamKind() && Entity.getDecl()) { + if (Entity.isParameterKind() && Entity.getDecl()) { if (Entity.getDecl()->getLocation().isInvalid()) return; @@ -7278,9 +7278,8 @@ void InitializationSequence::PrintInitLocationNote(Sema &S, << Entity.getDecl()->getDeclName(); else S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here); - } - else if (Entity.getKind() == InitializedEntity::EK_RelatedResult && - Entity.getMethodDecl()) + } else if (Entity.getKind() == InitializedEntity::EK_RelatedResult && + Entity.getMethodDecl()) S.Diag(Entity.getMethodDecl()->getLocation(), diag::note_method_return_type_change) << Entity.getMethodDecl()->getDeclName(); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index ceb32ee15dfa3..4d278bbc67d28 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1506,14 +1506,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, TemplateParameterList *TemplateParams = getGenericLambdaTemplateParameterList(LSI, *this); if (TemplateParams) { - for (const auto *TP : TemplateParams->asArray()) { + for (auto *TP : TemplateParams->asArray()) { if (!TP->getIdentifier()) continue; + CheckTemplateParameterRAII CTP(*this, TP); for (const auto &Capture : Intro.Captures) { - if (Capture.Id == TP->getIdentifier()) { + if (Capture.Id == TP->getIdentifier()) Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id; - NoteTemplateParameterLocation(*TP); - } } } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index aecf8ed1b4e4d..f3af514596a7e 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1580,9 +1580,13 @@ llvm::DenseSet &Sema::getLookupModules() { unsigned N = CodeSynthesisContexts.size(); for (unsigned I = CodeSynthesisContextLookupModules.size(); I != N; ++I) { - Module *M = CodeSynthesisContexts[I].Entity ? - getDefiningModule(*this, CodeSynthesisContexts[I].Entity) : - nullptr; + auto &Ctx = CodeSynthesisContexts[I]; + // FIXME: Are there any other context kinds that shouldn't be looked at + // here? + if (Ctx.Kind == CodeSynthesisContext::PartialOrderingTTP || + Ctx.Kind == CodeSynthesisContext::CheckTemplateParameter) + continue; + Module *M = Ctx.Entity ? getDefiningModule(*this, Ctx.Entity) : nullptr; if (M && !LookupModulesCache.insert(M).second) M = nullptr; CodeSynthesisContextLookupModules.push_back(M); @@ -3703,7 +3707,8 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, TemplateParameterList *Params = FD->getTemplateParameters(); if (Params->size() == 1) { IsTemplate = true; - if (!Params->getParam(0)->isTemplateParameterPack() && !StringLit) { + NamedDecl *Param = Params->getParam(0); + if (!Param->isTemplateParameterPack() && !StringLit) { // Implied but not stated: user-defined integer and floating literals // only ever use numeric literal operator templates, not templates // taking a parameter of class type. @@ -3716,6 +3721,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (StringLit) { SFINAETrap Trap(*this); CheckTemplateArgumentInfo CTAI; + CheckTemplateParameterRAII CTP(*this, Param); TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit); if (CheckTemplateArgument( Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(), diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 38fa3ff3ab5b4..3a1ed3ed8e677 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -869,9 +869,11 @@ void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl, ? diag::ext_template_param_shadow : (SupportedForCompatibility ? diag::ext_compat_template_param_shadow : diag::err_template_param_shadow); - const auto *ND = cast(PrevDecl); + auto *ND = cast(PrevDecl); + CheckTemplateParameterRAII CTP(*this, ND); + // FIXME: Don't put the name in the diagnostic, unless there is no source + // location. Diag(Loc, DiagId) << ND->getDeclName(); - NoteTemplateParameterLocation(*ND); } TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) { @@ -4824,7 +4826,7 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S, } bool Sema::CheckTemplateTypeArgument( - TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL, + TemplateArgumentLoc &AL, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted) { const TemplateArgument &Arg = AL.getArgument(); @@ -4880,7 +4882,6 @@ bool Sema::CheckTemplateTypeArgument( ? diag::ext_ms_template_type_arg_missing_typename : diag::err_template_arg_must_be_type_suggest) << FixItHint::CreateInsertion(Loc, "typename "); - NoteTemplateParameterLocation(*Param); // Recover by synthesizing a type using the location information that we // already have. @@ -4918,7 +4919,6 @@ bool Sema::CheckTemplateTypeArgument( // is not a type. SourceRange SR = AL.getSourceRange(); Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR; - NoteTemplateParameterLocation(*Param); return true; } @@ -5208,8 +5208,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, CheckTemplateArgumentInfo &CTAI, CheckTemplateArgumentKind CTAK) { // Check template type parameters. - if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) - return CheckTemplateTypeArgument(TTP, ArgLoc, CTAI.SugaredConverted, + if (isa(Param)) + return CheckTemplateTypeArgument(ArgLoc, CTAI.SugaredConverted, CTAI.CanonicalConverted); const TemplateArgument &Arg = ArgLoc.getArgument(); @@ -5354,8 +5354,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, // therefore cannot be a non-type template argument. Diag(ArgLoc.getLocation(), diag::err_template_arg_must_be_expr) << ArgLoc.getSourceRange(); - NoteTemplateParameterLocation(*Param); - return true; case TemplateArgument::Type: { @@ -5375,7 +5373,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T; else Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; - NoteTemplateParameterLocation(*Param); return true; } @@ -5466,11 +5463,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, } /// Diagnose a missing template argument. -template +template static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, - TemplateDecl *TD, - const TemplateParmDecl *D, - TemplateArgumentListInfo &Args) { + TemplateDecl *TD, const TemplateParmDecl *D, + TemplateArgumentListInfo &Args, + bool MatchingTTP) { // 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(cast(TD->getMostRecentDecl()) @@ -5488,16 +5485,12 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, return true; } + SourceLocation DiagLoc = Args.getRAngleLoc(); // FIXME: If there's a more recent default argument that *is* visible, // diagnose that it was declared too late. - - TemplateParameterList *Params = TD->getTemplateParameters(); - - S.Diag(Loc, diag::err_template_arg_list_different_arity) - << /*not enough args*/0 - << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD)) - << TD; - S.NoteTemplateLocation(*TD, Params->getSourceRange()); + S.Diag(DiagLoc.isValid() ? DiagLoc : Loc, + MatchingTTP ? diag::err_template_template_param_missing_param + : diag::err_template_param_missing_arg); return true; } @@ -5536,6 +5529,8 @@ bool Sema::CheckTemplateArgumentList( Param = ParamBegin; Param != ParamEnd; /* increment in loop */) { + CheckTemplateParameterRAII CTP1(*this, *Param); + if (size_t ParamIdx = Param - ParamBegin; DefaultArgs && ParamIdx >= DefaultArgs.StartPos) { // All written arguments should have been consumed by this point. @@ -5572,11 +5567,9 @@ bool Sema::CheckTemplateArgumentList( continue; } else if (ArgIdx == NumArgs && !PartialTemplateArgs) { // Not enough arguments for this parameter pack. - Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << /*not enough args*/0 - << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) - << Template; - NoteTemplateLocation(*Template, Params->getSourceRange()); + Diag(RAngleLoc, CTAI.MatchingTTP + ? diag::err_template_template_param_missing_param + : diag::err_template_param_missing_arg); return true; } } @@ -5589,8 +5582,10 @@ bool Sema::CheckTemplateArgumentList( if (ArgIsExpansion && CTAI.MatchingTTP) { SmallVector Args(ParamEnd - Param); + CTP1.Clear(); // Will continue processing parameters below. for (TemplateParameterList::iterator First = Param; Param != ParamEnd; ++Param) { + CheckTemplateParameterRAII CTP2(*this, *Param); TemplateArgument &Arg = Args[Param - First]; Arg = ArgLoc.getArgument(); if (!(*Param)->isTemplateParameterPack() || @@ -5631,7 +5626,6 @@ bool Sema::CheckTemplateArgumentList( diag::err_template_expansion_into_fixed_list) << (isa(Template) ? 1 : 0) << ArgLoc.getSourceRange(); - NoteTemplateParameterLocation(**Param); return true; } } @@ -5738,14 +5732,14 @@ bool Sema::CheckTemplateArgumentList( if (!HasDefaultArg) { if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, - NewArgs); + NewArgs, CTAI.MatchingTTP); if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*Param)) return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, - NewArgs); + NewArgs, CTAI.MatchingTTP); return diagnoseMissingArgument(*this, TemplateLoc, Template, cast(*Param), - NewArgs); + NewArgs, CTAI.MatchingTTP); } return true; } @@ -5801,8 +5795,7 @@ bool Sema::CheckTemplateArgumentList( // If we have any leftover arguments, then there were too many arguments. // Complain and fail. if (ArgIdx < NumArgs) { - Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << /*too many args*/1 + Diag(TemplateLoc, diag::err_template_too_many_args) << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc()); @@ -6227,8 +6220,6 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, << Arg->getType() << Arg->getSourceRange(); for (unsigned I = 0, N = Notes.size(); I != N; ++I) S.Diag(Notes[I].first, Notes[I].second); - - S.NoteTemplateParameterLocation(*Param); return NPV_Error; } @@ -6253,8 +6244,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // The types didn't match, but we know we got a null pointer; complain, // then recover as if the types were correct. S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant) - << Arg->getType() << ParamType << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); + << Arg->getType() << ParamType << Arg->getSourceRange(); return NPV_NullPointer; } @@ -6263,8 +6253,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // We could just return NPV_NotNullPointer, but we can print a better // message with the information we have here. S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid) - << EvalResult.Val.getAsString(S.Context, ParamType); - S.NoteTemplateParameterLocation(*Param); + << EvalResult.Val.getAsString(S.Context, ParamType); return NPV_Error; } @@ -6276,7 +6265,6 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code) << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()), ")"); - S.NoteTemplateParameterLocation(*Param); return NPV_NullPointer; } @@ -6317,7 +6305,6 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( S.Diag(Arg->getBeginLoc(), diag::err_template_arg_ref_bind_ignores_quals) << ParamType << Arg->getType() << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6335,7 +6322,6 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( else S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) << ArgIn->getType() << ParamType << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6478,7 +6464,6 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!Entity) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } @@ -6486,7 +6471,6 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (isa(Entity) || isa(Entity)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field) << Entity << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } @@ -6495,7 +6479,6 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!Method->isStatic()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method) << Method << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6535,7 +6518,6 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (Var->getType()->isReferenceType()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var) << Var->getType() << Arg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } @@ -6555,15 +6537,12 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!S.Context.hasSameUnqualifiedType(Entity->getType(), ParamType.getNonReferenceType())) { S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) - << ParamType; - S.NoteTemplateParameterLocation(*Param); + << ParamType; return true; } S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) - << ParamType - << FixItHint::CreateRemoval(AddrOpLoc); - S.NoteTemplateParameterLocation(*Param); + << ParamType << FixItHint::CreateRemoval(AddrOpLoc); ArgType = Entity->getType(); } @@ -6584,15 +6563,12 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( ArgType = S.Context.getPointerType(Entity->getType()); if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) - << ParamType; - S.NoteTemplateParameterLocation(*Param); + << ParamType; return true; } S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) - << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); - - S.NoteTemplateParameterLocation(*Param); + << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); } } @@ -6708,7 +6684,6 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, // We can't perform this conversion. S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible) << ResultArg->getType() << ParamType << ResultArg->getSourceRange(); - S.NoteTemplateParameterLocation(*Param); return true; } @@ -6814,7 +6789,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() << Arg->getSourceRange(); - NoteTemplateParameterLocation(*Param); return ExprError(); } } @@ -6823,10 +6797,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // declaration, but here we'll pass the argument location because that's // where the parameter type is deduced. ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc()); - if (ParamType.isNull()) { - NoteTemplateParameterLocation(*Param); + if (ParamType.isNull()) return ExprError(); - } } // We should have already dropped all cv-qualifiers by now. @@ -6858,9 +6830,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // not the type of the template argument deduced from A, against the // template parameter type. Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) - << Arg->getType() - << ParamType.getUnqualifiedType(); - NoteTemplateParameterLocation(*Param); + << Arg->getType() << ParamType.getUnqualifiedType(); return ExprError(); } @@ -6955,10 +6925,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Arg, ParamType, PartialOrderingTTP ? CCEK_InjectedTTP : CCEK_TemplateArg, Param); assert(!ArgResult.isUnset()); - if (ArgResult.isInvalid()) { - NoteTemplateParameterLocation(*Param); + if (ArgResult.isInvalid()) return ExprError(); - } } else { ArgResult = Arg; } @@ -7105,7 +7073,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (!ArgType->isIntegralOrEnumerationType()) { Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); - NoteTemplateParameterLocation(*Param); return ExprError(); } else if (!Arg->isValueDependent()) { class TmplArgICEDiagnoser : public VerifyICEDiagnoser { @@ -7143,7 +7110,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // We can't perform this conversion. Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) << Arg->getType() << ParamType << Arg->getSourceRange(); - NoteTemplateParameterLocation(*Param); return ExprError(); } @@ -7189,7 +7155,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative) << toString(OldValue, 10) << toString(Value, 10) << Param->getType() << Arg->getSourceRange(); - NoteTemplateParameterLocation(*Param); } // Complain if we overflowed the template parameter's type. @@ -7200,12 +7165,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, RequiredBits = OldValue.getActiveBits() + 1; else RequiredBits = OldValue.getSignificantBits(); - if (RequiredBits > AllowedBits) { + if (RequiredBits > AllowedBits) Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large) << toString(OldValue, 10) << toString(Value, 10) << Param->getType() << Arg->getSourceRange(); - NoteTemplateParameterLocation(*Param); - } } QualType T = ParamType->isEnumeralType() ? ParamType : IntegerType; @@ -7330,8 +7293,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) { case NPV_NotNullPointer: Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible) - << Arg->getType() << ParamType; - NoteTemplateParameterLocation(*Param); + << Arg->getType() << ParamType; return ExprError(); case NPV_Error: @@ -7359,7 +7321,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, static void DiagnoseTemplateParameterListArityMismatch( Sema &S, TemplateParameterList *New, TemplateParameterList *Old, - Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc); + Sema::TemplateParameterListEqualKind Kind); bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, @@ -7429,7 +7391,6 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, Diag(Arg.getLocation(), diag::err_template_template_parameter_not_at_least_as_constrained) << Template << Param << Arg.getSourceRange(); - Diag(Param->getLocation(), diag::note_entity_declared_at) << Param; Diag(Template->getLocation(), diag::note_entity_declared_at) << Template; MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template, TemplateAC); @@ -7438,25 +7399,24 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, return false; } -static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl, - unsigned HereDiagID, - unsigned ExternalDiagID) { - if (Decl.getLocation().isValid()) - return S.Diag(Decl.getLocation(), HereDiagID); - +SmallString<128> Sema::toTerseString(const NamedDecl &D) const { SmallString<128> Str; llvm::raw_svector_ostream Out(Str); - PrintingPolicy PP = S.getPrintingPolicy(); + PrintingPolicy PP = getPrintingPolicy(); PP.TerseOutput = 1; - Decl.print(Out, PP); - return S.Diag(Decl.getLocation(), ExternalDiagID) << Out.str(); + D.print(Out, PP); + return Str; } +// FIXME: Transform this into a context note. void Sema::NoteTemplateLocation(const NamedDecl &Decl, std::optional ParamRange) { + bool HasLoc = Decl.getLocation().isValid(); SemaDiagnosticBuilder DB = - noteLocation(*this, Decl, diag::note_template_decl_here, - diag::note_template_decl_external); + Diag(Decl.getLocation(), HasLoc ? diag::note_template_decl_here + : diag::note_template_decl_external); + if (!HasLoc) + DB << toTerseString(Decl).str(); if (ParamRange && ParamRange->isValid()) { assert(Decl.getLocation().isValid() && "Parameter range has location when Decl does not"); @@ -7464,11 +7424,6 @@ void Sema::NoteTemplateLocation(const NamedDecl &Decl, } } -void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { - noteLocation(*this, Decl, diag::note_template_param_here, - diag::note_template_param_external); -} - ExprResult Sema::BuildExpressionFromDeclTemplateArgument( const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, NamedDecl *TemplateParam) { @@ -7745,21 +7700,17 @@ Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, } /// Match two template parameters within template parameter lists. -static bool MatchTemplateParameterKind( - Sema &S, NamedDecl *New, - const Sema::TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old, - const NamedDecl *OldInstFrom, bool Complain, - Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) { +static bool +MatchTemplateParameterKind(Sema &S, NamedDecl *New, + const Sema::TemplateCompareNewDeclInfo &NewInstFrom, + NamedDecl *Old, const NamedDecl *OldInstFrom, + bool Complain, + Sema::TemplateParameterListEqualKind Kind) { // Check the actual kind (type, non-type, template). if (Old->getKind() != New->getKind()) { if (Complain) { - unsigned NextDiag = diag::err_template_param_different_kind; - if (TemplateArgLoc.isValid()) { - S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch); - NextDiag = diag::note_template_param_different_kind; - } - S.Diag(New->getLocation(), NextDiag) - << (Kind != Sema::TPL_TemplateMatch); + S.Diag(New->getLocation(), diag::err_template_param_different_kind) + << (Kind != Sema::TPL_TemplateMatch); S.Diag(Old->getLocation(), diag::note_template_prev_declaration) << (Kind != Sema::TPL_TemplateMatch); } @@ -7773,18 +7724,11 @@ static bool MatchTemplateParameterKind( // a parameter pack where the template template argument does not. if (Old->isTemplateParameterPack() != New->isTemplateParameterPack()) { if (Complain) { - unsigned NextDiag = diag::err_template_parameter_pack_non_pack; - if (TemplateArgLoc.isValid()) { - S.Diag(TemplateArgLoc, - diag::err_template_arg_template_params_mismatch); - NextDiag = diag::note_template_parameter_pack_non_pack; - } - unsigned ParamKind = isa(New)? 0 : isa(New)? 1 : 2; - S.Diag(New->getLocation(), NextDiag) - << ParamKind << New->isParameterPack(); + S.Diag(New->getLocation(), diag::err_template_parameter_pack_non_pack) + << ParamKind << New->isParameterPack(); S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here) << ParamKind << Old->isParameterPack(); } @@ -7805,13 +7749,8 @@ static bool MatchTemplateParameterKind( QualType NewType = S.Context.getUnconstrainedType(NewNTTP->getType()); if (!S.Context.hasSameType(OldType, NewType)) { if (Complain) { - unsigned NextDiag = diag::err_template_nontype_parm_different_type; - if (TemplateArgLoc.isValid()) { - S.Diag(TemplateArgLoc, - diag::err_template_arg_template_params_mismatch); - NextDiag = diag::note_template_nontype_parm_different_type; - } - S.Diag(NewNTTP->getLocation(), NextDiag) + S.Diag(NewNTTP->getLocation(), + diag::err_template_nontype_parm_different_type) << NewNTTP->getType() << (Kind != Sema::TPL_TemplateMatch); S.Diag(OldNTTP->getLocation(), diag::note_template_nontype_parm_prev_declaration) @@ -7832,8 +7771,7 @@ static bool MatchTemplateParameterKind( OldTTP->getTemplateParameters(), Complain, (Kind == Sema::TPL_TemplateMatch ? Sema::TPL_TemplateTemplateParmMatch - : Kind), - TemplateArgLoc)) + : Kind))) return false; } @@ -7884,21 +7822,12 @@ static bool MatchTemplateParameterKind( /// Diagnose a known arity mismatch when comparing template argument /// lists. -static -void DiagnoseTemplateParameterListArityMismatch(Sema &S, - TemplateParameterList *New, - TemplateParameterList *Old, - Sema::TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc) { - unsigned NextDiag = diag::err_template_param_list_different_arity; - if (TemplateArgLoc.isValid()) { - S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch); - NextDiag = diag::note_template_param_list_different_arity; - } - S.Diag(New->getTemplateLoc(), NextDiag) - << (New->size() > Old->size()) - << (Kind != Sema::TPL_TemplateMatch) - << SourceRange(New->getTemplateLoc(), New->getRAngleLoc()); +static void DiagnoseTemplateParameterListArityMismatch( + Sema &S, TemplateParameterList *New, TemplateParameterList *Old, + Sema::TemplateParameterListEqualKind Kind) { + S.Diag(New->getTemplateLoc(), diag::err_template_param_list_different_arity) + << (New->size() > Old->size()) << (Kind != Sema::TPL_TemplateMatch) + << SourceRange(New->getTemplateLoc(), New->getRAngleLoc()); S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration) << (Kind != Sema::TPL_TemplateMatch) << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc()); @@ -7907,11 +7836,10 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S, bool Sema::TemplateParameterListsAreEqual( const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, - TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) { + TemplateParameterListEqualKind Kind) { if (Old->size() != New->size()) { if (Complain) - DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, - TemplateArgLoc); + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind); return false; } @@ -7929,21 +7857,18 @@ bool Sema::TemplateParameterListsAreEqual( OldParm != OldParmEnd; ++OldParm, ++NewParm) { if (NewParm == NewParmEnd) { if (Complain) - DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, - TemplateArgLoc); + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind); return false; } if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm, - OldInstFrom, Complain, Kind, - TemplateArgLoc)) + OldInstFrom, Complain, Kind)) return false; } // Make sure we exhausted all of the arguments. if (NewParm != NewParmEnd) { if (Complain) - DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, - TemplateArgLoc); + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind); return false; } @@ -8238,7 +8163,6 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs( S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(), diag::err_dependent_typed_non_type_arg_in_partial_spec) << Param->getType(); - S.NoteTemplateParameterLocation(*Param); return true; } } @@ -8262,6 +8186,7 @@ bool Sema::CheckTemplatePartialSpecializationArgs( if (!Param) continue; + CheckTemplateParameterRAII CTP(*this, Param); if (CheckNonTypeTemplatePartialSpecializationArgs(*this, TemplateNameLoc, Param, &TemplateArgs[I], 1, I >= NumExplicit)) diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 627cd82ed1c77..5e006eab88c97 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3006,7 +3006,7 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, // arguments). S.Diag(Param->getLocation(), diag::err_template_arg_deduced_incomplete_pack) - << Arg << Param; + << Arg << Param; return true; } if (ConvertArg(InnerArg, SugaredPackedArgsBuilder.size())) @@ -3072,7 +3072,7 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { NamedDecl *Param = TemplateParams->getParam(I); - + Sema::CheckTemplateParameterRAII CTP(S, Param); // C++0x [temp.arg.explicit]p3: // A trailing template parameter pack (14.5.3) not otherwise deduced will // be deduced to an empty sequence of template arguments. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index fcb7671ed92f0..f2c0dfdf639a6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -575,6 +575,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const { case BuildingDeductionGuides: case TypeAliasTemplateInstantiation: case PartialOrderingTTP: + case CheckTemplateParameter: return false; // This function should never be called when Kind's value is Memoization. @@ -809,7 +810,16 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( Sema &SemaRef, SourceLocation ArgLoc, PartialOrderingTTP, TemplateDecl *PArg, SourceRange InstantiationRange) : InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP, - ArgLoc, InstantiationRange, PArg) {} + ArgLoc, SourceRange(), PArg) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + CheckTemplateParameter, + NamedDecl *Param) + : InstantiatingTemplate( + SemaRef, CodeSynthesisContext::CheckTemplateParameter, + Param->getLocation(), Param->getSourceRange(), Param) { + assert(Param->isTemplateParameter()); +} void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) { Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext; @@ -1251,12 +1261,18 @@ void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) { case CodeSynthesisContext::PartialOrderingTTP: DiagFunc(Active->PointOfInstantiation, PDiag(diag::note_template_arg_template_params_mismatch)); - if (SourceLocation ParamLoc = Active->Entity->getLocation(); - ParamLoc.isValid()) - DiagFunc(ParamLoc, PDiag(diag::note_template_prev_declaration) - << /*isTemplateTemplateParam=*/true - << Active->InstantiationRange); break; + case CodeSynthesisContext::CheckTemplateParameter: { + const auto &ND = *cast(Active->Entity); + if (SourceLocation Loc = ND.getLocation(); Loc.isValid()) { + DiagFunc(Loc, PDiag(diag::note_template_param_here) + << ND.getSourceRange()); + break; + } + DiagFunc(SourceLocation(), PDiag(diag::note_template_param_external) + << toTerseString(ND).str()); + break; + } } } } @@ -1300,6 +1316,7 @@ std::optional Sema::isSFINAEContext() const { case CodeSynthesisContext::DefaultTemplateArgumentChecking: case CodeSynthesisContext::RewritingOperatorAsSpaceship: case CodeSynthesisContext::PartialOrderingTTP: + case CodeSynthesisContext::CheckTemplateParameter: // A default template argument instantiation and substitution into // template parameters with arguments for prior parameters may or may // not be a SFINAE context; look further up the stack. @@ -2348,6 +2365,7 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( ExprResult TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { + Sema::CheckTemplateParameterRAII CTP(SemaRef, E->getParameter()); ExprResult SubstReplacement = E->getReplacement(); if (!isa(SubstReplacement.get())) SubstReplacement = TransformExpr(E->getReplacement()); diff --git a/clang/test/AST/ByteCode/cxx1z.cpp b/clang/test/AST/ByteCode/cxx1z.cpp index 57f99235a2b20..ca5f10f6567b4 100644 --- a/clang/test/AST/ByteCode/cxx1z.cpp +++ b/clang/test/AST/ByteCode/cxx1z.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=expected,both %s // RUN: %clang_cc1 -std=c++17 -verify=ref,both %s -template struct A {}; +template struct A {}; // both-note 6{{template parameter is declared here}} namespace Temp { struct S { int n; }; constexpr S &addr(S &&s) { return s; } diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp index 06501de64916a..d39c2281ec146 100644 --- a/clang/test/AST/ByteCode/cxx20.cpp +++ b/clang/test/AST/ByteCode/cxx20.cpp @@ -897,7 +897,7 @@ namespace VirtDtor { } namespace TemporaryInNTTP { - template struct B { /* ... */ }; + template struct B { /* ... */ }; // both-note {{template parameter is declared here}} struct J1 { J1 *self=this; }; diff --git a/clang/test/AST/ByteCode/cxx98.cpp b/clang/test/AST/ByteCode/cxx98.cpp index c17049b01c1da..9af668029f8a3 100644 --- a/clang/test/AST/ByteCode/cxx98.cpp +++ b/clang/test/AST/ByteCode/cxx98.cpp @@ -6,7 +6,7 @@ namespace IntOrEnum { const int k = 0; const int &p = k; // both-note {{declared here}} - template struct S {}; + template struct S {}; // both-note {{template parameter is declared here}} S

s; // both-error {{not an integral constant expression}} \ // both-note {{read of variable 'p' of non-integral, non-enumeration type 'const int &'}} } diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index cb3d6111fd2bf..48f856fdd2c07 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -413,7 +413,7 @@ namespace DeriveFailures { constexpr Derived(int i) : OtherVal(i) {} // ref-error {{never produces a constant expression}} \ // both-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} \ - // ref-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} + // ref-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} }; constexpr Derived D(12); // both-error {{must be initialized by a constant expression}} \ @@ -1740,9 +1740,9 @@ namespace CtorOfInvalidClass { // both-error {{must be initialized by a constant expression}} #if __cplusplus >= 202002L - template + template // both-note {{template parameter is declared here}} concept ReferenceOf = Q; - /// This calls a valid and constexpr copy constructor of InvalidCtor, + /// This calls a valid and constexpr copy constructor of InvalidCtor, /// but should still be rejected. template auto R, typename Rep> int F; // both-error {{non-type template argument is not a constant expression}} #endif diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp index 9632fda296aa1..fc4e359666ba9 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp @@ -33,5 +33,6 @@ namespace test1 { // specifiers. namespace test2 { template struct bar {}; + // expected-note@-1 {{template parameter is declared here}} template struct foo : bar {}; // expected-error {{use of class template 'foo' requires template arguments}} expected-note {{template is declared here}} } diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp index 2bceb3e267790..57c99212f4c69 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp @@ -251,5 +251,5 @@ void P1957R2(void *a, int *b, Agg *c, int Agg::*d) { Agg tc = {c}; // expected-error {{cannot be narrowed}} expected-note {{}} Agg td = {d}; // expected-error {{cannot be narrowed}} expected-note {{}} } -template struct BoolParam {}; +template struct BoolParam {}; // expected-note {{template parameter is declared here}} BoolParam<&P1957R2> bp; // expected-error {{not allowed in a converted constant expression}} diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 282e71bbf3bda..c035aa3f4ec61 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -806,6 +806,7 @@ namespace cwg49 { // cwg49: 2.8 // since-cxx17-error@#cwg49-c {{non-type template argument is not a constant expression}} // since-cxx17-note@#cwg49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}} // since-cxx17-note@#cwg49-q {{declared here}} + // since-cxx17-note@#cwg49-A {{template parameter is declared here}} } // namespace cwg49 namespace cwg50 { // cwg50: 2.7 @@ -1018,9 +1019,9 @@ namespace cwg62 { // cwg62: 2.9 struct A { struct { int n; } b; }; - template struct X {}; - template T get() { return get(); } - template int take(T) { return 0; } + template struct X {}; // #cwg62-X + template T get() { return get(); } // #cwg62-get + template int take(T) { return 0; } // #cwg62-take X x1; A a = get(); @@ -1034,22 +1035,27 @@ namespace cwg62 { // cwg62: 2.9 X x2; // cxx98-error@-1 {{template argument uses unnamed type}} + // cxx98-note@#cwg62-X {{template parameter is declared here}} // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} X x3; // cxx98-error@-1 {{template argument uses unnamed type}} + // cxx98-note@#cwg62-X {{template parameter is declared here}} // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} NoNameForLinkagePtr p1 = get(); // cxx98-error@-1 {{template argument uses unnamed type}} + // cxx98-note@#cwg62-get {{template parameter is declared here}} // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} - // cxx98-note@-3 {{while substituting explicitly-specified template arguments}} + // cxx98-note@-4 {{while substituting explicitly-specified template arguments}} NoNameForLinkagePtr p2 = get(); // cxx98-error@-1 {{template argument uses unnamed type}} + // cxx98-note@#cwg62-get {{template parameter is declared here}} // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} - // cxx98-note@-3 {{while substituting explicitly-specified template arguments}} + // cxx98-note@-4 {{while substituting explicitly-specified template arguments}} int n1 = take(noNameForLinkagePtr); // cxx98-error@-1 {{template argument uses unnamed type}} + // cxx98-note@#cwg62-take {{template parameter is declared here}} // cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}} - // cxx98-note@-3 {{while substituting deduced template arguments}} + // cxx98-note@-4 {{while substituting deduced template arguments}} X x4; @@ -1057,18 +1063,24 @@ namespace cwg62 { // cwg62: 2.9 struct NoLinkage {}; X a; // cxx98-error@-1 {{template argument uses local type }} + // cxx98-note@#cwg62-X {{template parameter is declared here}} X b; // cxx98-error@-1 {{template argument uses local type }} + // cxx98-note@#cwg62-X {{template parameter is declared here}} get(); // cxx98-error@-1 {{template argument uses local type }} - // cxx98-note@-2 {{while substituting explicitly-specified template arguments}} + // cxx98-note@#cwg62-get {{template parameter is declared here}} + // cxx98-note@-3 {{while substituting explicitly-specified template arguments}} get(); // cxx98-error@-1 {{template argument uses local type }} - // cxx98-note@-2 {{while substituting explicitly-specified template arguments}} + // cxx98-note@#cwg62-get {{template parameter is declared here}} + // cxx98-note@-3 {{while substituting explicitly-specified template arguments}} X c; // cxx98-error@-1 {{template argument uses local type }} + // cxx98-note@#cwg62-X {{template parameter is declared here}} X d; // cxx98-error@-1 {{template argument uses local type }} + // cxx98-note@#cwg62-X {{template parameter is declared here}} } } // namespace cwg62 @@ -1135,10 +1147,11 @@ namespace cwg69 { // cwg69: 9 extern template void f(); // cxx98-error@-1 {{extern templates are a C++11 extension}} // expected-error@-2 {{explicit instantiation declaration of 'f' with internal linkage}} - template struct Q {}; + template struct Q {}; // #cwg69-Q Q<&f > q; // cxx98-error@-1 {{non-type template argument referring to function 'f' with internal linkage is a C++11 extension}} // cxx98-note@#cwg69-f {{non-type template argument refers to function here}} + // cxx98-note@#cwg69-Q {{template parameter is declared here}} } // namespace cwg69 namespace cwg70 { // cwg70: 2.7 diff --git a/clang/test/CXX/drs/cwg10xx.cpp b/clang/test/CXX/drs/cwg10xx.cpp index c5b96c4ab8ffc..10ee50558c7e8 100644 --- a/clang/test/CXX/drs/cwg10xx.cpp +++ b/clang/test/CXX/drs/cwg10xx.cpp @@ -43,6 +43,7 @@ namespace cwg1004 { // cwg1004: 5 template class U = T::template A> struct Third { }; // expected-error@-1 {{is a constructor name}} // expected-note@#cwg1004-t {{in instantiation of default argument}} + // expected-note@-3 {{template parameter is declared here}} Third > t; // #cwg1004-t } // namespace cwg1004 diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp index 9c72fefb5b65c..8a9f285673699 100644 --- a/clang/test/CXX/drs/cwg13xx.cpp +++ b/clang/test/CXX/drs/cwg13xx.cpp @@ -180,6 +180,7 @@ namespace cwg1315 { // cwg1315: partial // dependent type of T::value is not the same as 'int'. // A core issue will be opened to decide what is supposed to happen here. template struct C; + // expected-note@-1 {{template parameter is declared here}} template struct C; // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}} } // namespace cwg1315 diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 626473f11d3ec..5f40fe469b01b 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -26,6 +26,7 @@ S V; // #cwg1801-S-i // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#cwg1801-S {{template parameter is declared here}} // cxx17-error@#cwg1801-S-i {{non-type template argument refers to subobject '.i'}} +// cxx17-note@#cwg1801-S {{template parameter is declared here}} } // namespace cwg1801 namespace cwg1802 { // cwg1802: 3.1 @@ -381,13 +382,13 @@ struct A { struct B { void e(); }; - + void f(); - + struct D { void g(); }; - + T h(); template @@ -399,13 +400,13 @@ struct A { struct B { void e(); }; - + int f(); - + struct D { void g(); }; - + template int i(); }; @@ -430,11 +431,11 @@ class C { template friend void A::D::g(); // expected-warning@-1 {{dependent nested name specifier 'A::D::' for friend class declaration is not supported; turning off access control for 'C'}} - + template friend int *A::h(); // expected-warning@-1 {{dependent nested name specifier 'A::' for friend class declaration is not supported; turning off access control for 'C'}} - + template template friend T A::i(); @@ -451,7 +452,7 @@ template void A::f() { (void)c.private_int; } int A::f() { (void)c.private_int; return 0; } -// FIXME: both definition of 'D::g' are not friends, so they don't have access to 'private_int' +// FIXME: both definition of 'D::g' are not friends, so they don't have access to 'private_int' template void A::D::g() { (void)c.private_int; } void A::D::g() { (void)c.private_int; } diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp index 15bcc20b7fa2a..51f320fc43cfa 100644 --- a/clang/test/CXX/drs/cwg1xx.cpp +++ b/clang/test/CXX/drs/cwg1xx.cpp @@ -26,18 +26,22 @@ namespace cwg100 { // cwg100: 2.7 // cxx98-14-error@#cwg100-a {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#cwg100-A {{template parameter is declared here}} // since-cxx17-error@#cwg100-a {{pointer to string literal is not allowed in a template argument}} + // since-cxx17-note@#cwg100-A {{template parameter is declared here}} B<"bar"> b; // #cwg100-b // cxx98-14-error@#cwg100-b {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#cwg100-B {{template parameter is declared here}} // since-cxx17-error@#cwg100-b {{reference to string literal is not allowed in a template argument}} + // since-cxx17-note@#cwg100-B {{template parameter is declared here}} C<"baz"> c; // #cwg100-c // cxx98-14-error@#cwg100-c {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#cwg100-C {{template parameter is declared here}} // since-cxx17-error@#cwg100-c {{pointer to subobject of string literal is not allowed in a template argument}} + // since-cxx17-note@#cwg100-C {{template parameter is declared here}} D<*"quux"> d; // #cwg100-d // cxx98-14-error@#cwg100-d {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#cwg100-D {{template parameter is declared here}} // since-cxx17-error@#cwg100-d {{reference to subobject of string literal is not allowed in a template argument}} + // since-cxx17-note@#cwg100-D {{template parameter is declared here}} } // namespace cwg100 namespace cwg101 { // cwg101: 3.5 @@ -152,15 +156,17 @@ namespace cwg112 { // cwg112: 3.1 volatile T a2[1] = {}; const Arr a3 = {}; // #cwg112-a3 volatile Arr a4 = {}; - template struct X {}; + template struct X {}; // #cwg112-X // FIXME: Test this somehow in C++11 and on. X x1; // cxx98-error@-1 {{non-type template argument referring to object 'a1' with internal linkage is a C++11 extension}} // cxx98-note@#cwg112-a1 {{non-type template argument refers to object here}} + // cxx98-note@#cwg112-X {{template parameter is declared here}} X x2; X x3; // cxx98-error@-1 {{non-type template argument referring to object 'a3' with internal linkage is a C++11 extension}} // cxx98-note@#cwg112-a3 {{non-type template argument refers to object here}} + // cxx98-note@#cwg112-X {{template parameter is declared here}} X x4; } // namespace cwg112 @@ -634,7 +640,7 @@ namespace example3 { struct Base { private: static const int i = 10; // #cwg138-ex3-Base-i - + public: struct Data; // Elaborated type specifier is not the sole constituent of declaration, @@ -648,7 +654,7 @@ struct Base { }; }; struct Data { - void f() { + void f() { int i2 = Base::i; // expected-error@-1 {{'i' is a private member of 'cwg138::example3::Base'}} // expected-note@#cwg138-ex3-Base-i {{declared private here}} @@ -1309,8 +1315,8 @@ namespace cwg184 { // cwg184: 2.7 template class T> void A::f() { // #cwg184-T T<> t; - // expected-error@-1 {{too few template arguments for template template parameter 'T'}} - // expected-note@#cwg184-T {{template is declared here}} + // expected-error@-1 {{missing template argument for template parameter}} + // expected-note@#cwg184-T {{template parameter is declared here}} } template class T> void A::g() { diff --git a/clang/test/CXX/drs/cwg20xx.cpp b/clang/test/CXX/drs/cwg20xx.cpp index 141a1012aef93..fd31a51f79ec5 100644 --- a/clang/test/CXX/drs/cwg20xx.cpp +++ b/clang/test/CXX/drs/cwg20xx.cpp @@ -27,7 +27,7 @@ int b = __builtin_addressof(b2)->foo; // cwg2009: na namespace cwg2026 { // cwg2026: 11 - template struct X {}; + template struct X {}; // #cwg2026-X const int a = a + 1; // #cwg2026-a // expected-warning@-1 {{variable 'a' is uninitialized when used within its own initialization}} @@ -35,9 +35,11 @@ namespace cwg2026 { // cwg2026: 11 // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}} // cxx98-note@-2 {{initializer of 'a' is not a constant expression}} // cxx98-note@#cwg2026-a {{declared here}} + // cxx98-note@#cwg2026-X {{template parameter is declared here}} // since-cxx11-error@#cwg2026-xa {{non-type template argument is not a constant expression}} // since-cxx11-note@#cwg2026-xa {{initializer of 'a' is not a constant expression}} // since-cxx11-note@#cwg2026-a {{declared here}} + // since-cxx11-note@#cwg2026-X {{template parameter is declared here}} #if __cplusplus >= 201103L constexpr int b = b; @@ -65,9 +67,11 @@ namespace cwg2026 { // cwg2026: 11 // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}} // cxx98-note@-2 {{initializer of 'e' is not a constant expression}} // cxx98-note@#cwg2026-e {{declared here}} + // cxx98-note@#cwg2026-X {{template parameter is declared here}} // since-cxx11-error@#cwg2026-xe {{non-type template argument is not a constant expression}} // since-cxx11-note@#cwg2026-xe {{initializer of 'e' is not a constant expression}} // since-cxx11-note@#cwg2026-e {{declared here}} + // since-cxx11-note@#cwg2026-X {{template parameter is declared here}} #if __cplusplus >= 201103L static constexpr int f = f; @@ -149,7 +153,7 @@ namespace cwg2076 { // cwg2076: 13 operator string_view() const; }; - void foo(const string &); // #cwg2076-foo + void foo(const string &); // #cwg2076-foo void bar(string_view); // #cwg2076-bar void func(const string &arg) { @@ -429,7 +433,7 @@ int f() return 0; } } // namespace GH42233 -} // namespace cwg2091 +} // namespace cwg2091 namespace cwg2094 { // cwg2094: 5 struct A { int n; }; diff --git a/clang/test/CXX/drs/cwg21xx.cpp b/clang/test/CXX/drs/cwg21xx.cpp index 42a7c4d7bbded..97bf320658759 100644 --- a/clang/test/CXX/drs/cwg21xx.cpp +++ b/clang/test/CXX/drs/cwg21xx.cpp @@ -24,7 +24,7 @@ namespace std { } namespace cwg2100 { // cwg2100: 12 - template struct X {}; + template struct X {}; // #cwg2100-X template struct A { static const int n = 1; int f() { @@ -35,6 +35,7 @@ namespace cwg2100 { // cwg2100: 12 return X<&n>::n; // ok, value-dependent // cxx98-14-error@-1 {{non-type template argument refers to object 'n' that does not have linkage}} // cxx98-14-note@#cwg2100-n {{non-type template argument refers to object here}} + // cxx98-14-note@#cwg2100-X {{template parameter is declared here}} } }; template struct X

{ diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp index 6c420ecd4c91d..a616120b82063 100644 --- a/clang/test/CXX/drs/cwg3xx.cpp +++ b/clang/test/CXX/drs/cwg3xx.cpp @@ -317,18 +317,20 @@ namespace cwg319 { // cwg319: no typedef int (*pa)[n1]; pa parr; // ok, type has linkage despite using 'n1' - template struct X {}; + template struct X {}; // #cwg319-X void f() { struct A { int n; }; extern A a; // FIXME: ill-formed X xa; // cxx98-error@-1 {{template argument uses local type 'A'}} + // cxx98-note@#cwg319-X {{template parameter is declared here}} typedef A B; extern B b; // FIXME: ill-formed X xb; // cxx98-error@-1 {{template argument uses local type 'A'}} + // cxx98-note@#cwg319-X {{template parameter is declared here}} const int n = 1; typedef int (*C)[n]; @@ -997,6 +999,7 @@ namespace cwg354 { // cwg354: 3.1 c++11 // since-cxx17-note@#cwg354-ptr_mem {{template parameter is declared here}} ptr_mem<(int S::*)0> m1; // cxx98-error@-1 {{non-type template argument is not a pointer to member constant}} + // cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}} ptr_mem<(float S::*)0> m2; // #cwg354-m2 // cxx98-error@#cwg354-m2 {{non-type template argument of type 'float S::*' cannot be converted to a value of type 'int S::*'}} // cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}} @@ -1502,7 +1505,7 @@ namespace cwg389 { // cwg389: no typedef struct {} const C; // #cwg389-C typedef enum {} const D; // #cwg389-D }; - template struct T {}; + template struct T {}; // #cwg389-T struct WithLinkage1 {}; enum WithLinkage2 {}; @@ -1543,18 +1546,23 @@ namespace cwg389 { // cwg389: no typedef T BadArg1; // expected-error@-1 {{template argument uses unnamed type}} + // expected-note@#cwg389-T {{template parameter is declared here}} // expected-note@#cwg389-no-link-1 {{unnamed type used in template argument was declared here}} typedef T BadArg2; // expected-error@-1 {{template argument uses unnamed type}} + // expected-note@#cwg389-T {{template parameter is declared here}} // expected-note@#cwg389-no-link-2 {{unnamed type used in template argument was declared here}} typedef T BadArg3; // expected-error@-1 {{template argument uses unnamed type}} + // expected-note@#cwg389-T {{template parameter is declared here}} // expected-note@#cwg389-C {{unnamed type used in template argument was declared here}} typedef T BadArg4; // expected-error@-1 {{template argument uses unnamed type}} + // expected-note@#cwg389-T {{template parameter is declared here}} // expected-note@#cwg389-D {{unnamed type used in template argument was declared here}} typedef T BadArg5; // expected-error@-1 {{template argument uses unnamed type}} + // expected-note@#cwg389-T {{template parameter is declared here}} // expected-note@#cwg389-C {{unnamed type used in template argument was declared here}} #endif diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp index 0debc104ac45b..78b03b3df2323 100644 --- a/clang/test/CXX/drs/cwg4xx.cpp +++ b/clang/test/CXX/drs/cwg4xx.cpp @@ -43,12 +43,15 @@ namespace cwg401 { // cwg401: 2.8 // expected-error@#cwg401-A {{'type' is a private member of 'cwg401::C'}} // expected-note@#cwg402-friend-A-C {{in instantiation of default argument for 'A' required here}} // expected-note@#cwg402-C-type {{implicitly declared private here}} + // expected-note@#cwg401-A {{template parameter is declared here}} // expected-error@#cwg401-A {{'type' is a protected member of 'cwg401::B'}} // expected-note@#cwg402-b {{in instantiation of default argument for 'A' required here}} // expected-note@#cwg402-B-type {{declared protected here}} + // expected-note@#cwg401-A {{template parameter is declared here}} // expected-error@#cwg401-A {{'type' is a private member of 'cwg401::D'}} // expected-note@#cwg402-d {{in instantiation of default argument for 'A' required here}} // expected-note@#cwg402-D-type {{implicitly declared private here}} + // expected-note@#cwg401-A {{template parameter is declared here}} class B { protected: typedef int type; // #cwg402-B-type @@ -80,8 +83,9 @@ namespace cwg401 { // cwg401: 2.8 // to not treat the default template argument as a SFINAE context in C++98. template void f(T) {} // #cwg402-f // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} - // cxx98-error@-2 {{'type' is a protected member of 'cwg401::B'}} - // cxx98-note@-3 {{in instantiation of default argument for 'f' required here}} + // cxx98-note@-2 {{template parameter is declared here}} + // cxx98-error@-3 {{'type' is a protected member of 'cwg401::B'}} + // cxx98-note@-4 {{in instantiation of default argument for 'f' required here}} // cxx98-note@#cwg402-f-b {{while substituting deduced template arguments into function template 'f' [with T = B, U = (no value)]}} // cxx98-note@#cwg402-B-type {{declared protected here}} void g(B b) { f(b); } // #cwg402-f-b @@ -636,15 +640,17 @@ namespace cwg431 { // cwg431: 2.8 } // namespace cwg431 namespace cwg432 { // cwg432: 3.0 - template struct A {}; + template struct A {}; // #cwg432-A template struct B : A {}; // expected-error@-1 {{use of class template 'B' requires template arguments}} - // expected-note@-2 {{template is declared here}} + // expected-note@#cwg432-A {{template parameter is declared here}} + // expected-note@-3 {{template is declared here}} template struct C : A > {}; #if __cplusplus >= 201103L template struct D : decltype(A()) {}; // since-cxx11-error@-1 {{use of class template 'D' requires template arguments}} - // since-cxx11-note@-2 {{template is declared here}} + // since-cxx11-note@#cwg432-A {{template parameter is declared here}} + // since-cxx11-note@-3 {{template is declared here}} #endif } // namespace cwg432 @@ -1377,6 +1383,7 @@ namespace cwg487 { // cwg487: 2.7 namespace cwg488 { // cwg488: 2.9 c++11 template void f(T); + // cxx98-note@-1 {{template parameter is declared here}} void f(int); void g() { // FIXME: It seems CWG thought this should be a SFINAE failure prior to diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp index fb6acde459d9c..11a77575c70c1 100644 --- a/clang/test/CXX/drs/cwg6xx.cpp +++ b/clang/test/CXX/drs/cwg6xx.cpp @@ -79,10 +79,11 @@ namespace cwg602 { // cwg602: 2.7 } // namespace cwg602 namespace cwg603 { // cwg603: 3.1 - template struct S {}; + template struct S {}; // #cwg603-S typedef S<'\001'> S1; typedef S<(1ul << __CHAR_BIT__) + 1> S1; // since-cxx11-error@-1 {{non-type template argument evaluates to 257, which cannot be narrowed to type 'unsigned char'}} + // since-cxx11-note@#cwg603-S {{template parameter is declared here}} } // namespace cwg603 // cwg604: na @@ -407,7 +408,7 @@ namespace cwg638 { // cwg638: no class X { typedef int type; - template friend struct A::B; + template friend struct A::B; // expected-warning@-1 {{dependent nested name specifier 'A::' for friend class declaration is not supported; turning off access control for 'X'}} template friend void A::f(); // expected-warning@-1 {{dependent nested name specifier 'A::' for friend class declaration is not supported; turning off access control for 'X'}} @@ -1078,7 +1079,7 @@ namespace cwg677 { // cwg677: no struct A { void *operator new(std::size_t); void operator delete(void*) = delete; // #cwg677-A-delete - // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} }; struct B { void *operator new(std::size_t); diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp index 3eedef3cf7712..f40e1af14d111 100644 --- a/clang/test/CXX/expr/expr.const/p3-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp @@ -4,7 +4,7 @@ // A converted constant expression of type T is a core constant expression, int nonconst = 8; // expected-note 3 {{here}} enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}} -template struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} +template struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} expected-note {{template parameter is declared here}} void NonConstF() { switch (nonconst) { case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}} @@ -66,7 +66,7 @@ enum class EEE : unsigned short { e = 123456, // expected-error {{enumerator value evaluates to 123456, which cannot be narrowed to type 'unsigned short'}} f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be narrowed to type 'unsigned short'}} }; -template using A = int; // cxx17-note 2{{template parameter is declared here}} +template using A = int; // expected-note 4{{template parameter is declared here}} using Int = A; using Int = A; // expected-error {{not implicitly convertible}} @@ -79,7 +79,8 @@ using Int = A<-3>; // expected-error {{template argument evaluates to -3, which // integral conversions as well as boolean conversions. // FIXME: Per core issue 1407, this is not correct. template struct Val { static constexpr T value = v; }; -// cxx17-note@-1 2{{template parameter is declared here}} +// cxx17-note@-1 1{{template parameter is declared here}} +// expected-note@-2 2{{template parameter is declared here}} static_assert(Val::value == 1, ""); // ok static_assert(Val::value == 0, ""); // ok static_assert(Val::value == 1, ""); // ok diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp index 5433cfb21955d..2572e766cb263 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -77,7 +77,7 @@ using r2i3 = r2; // expected-error{{constraints not satisfied for clas namespace ns2 { template struct identity {}; - template requires requires { typename identity; } // expected-note 2{{because 'typename identity' would be invalid: too few template arguments for class template 'identity'}} + template requires requires { typename identity; } // expected-note 2{{because 'typename identity' would be invalid: missing template argument for template parameter}} struct r4 {}; using r4i1 = r4; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = ]}} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp index 692958ef565cf..332f69bacb69e 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp @@ -9,7 +9,7 @@ template struct IP { // expected-note 6 {{template parameter is declar IP *ip2; }; -template struct IR {}; +template struct IR {}; // expected-note {{template parameter is declared here}} constexpr std::nullptr_t get_nullptr() { return nullptr; } diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp index 629000d88acc3..e979051e23419 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -31,16 +31,16 @@ namespace non_type_tmpl_param { // omitted if the name refers to a function or array and shall be omitted // if the corresopnding template-parameter is a reference; or namespace addr_of_obj_or_func { - template struct X0 { }; // expected-note 5{{here}} + template struct X0 { }; // expected-note 5{{here}} cxx17-note 2{{here}} #if __cplusplus >= 201103L // precxx17-note@-2 2{{template parameter is declared here}} #endif - template struct X1 { }; // cxx17-note {{here}} + template struct X1 { }; // cxx17-note {{here}} precxx17-note{{here}} #if __cplusplus <= 199711L // precxx17-note@-2 {{here}} #endif - template struct X2 { }; // expected-note 4{{here}} + template struct X2 { }; // expected-note 5{{here}} template struct X2k { }; // expected-note {{here}} template struct X3 { }; // expected-note 4{{here}} @@ -180,6 +180,7 @@ namespace addr_of_obj_or_func { namespace bad_args { template struct X0 { }; // precxx17-note 4{{template parameter is declared here}} + // cxx17-note@-1 3{{template parameter is declared here}} int i = 42; X0<&i + 2> x0a; // precxx17-error{{non-type template argument does not refer to any declaration}} \ cxx17-error {{non-type template argument is not a constant expression}} \ diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp index 034ad49d0715c..bb7512a95ed3b 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -48,9 +48,9 @@ namespace pointer_to_object_parameters { X(int, int); operator int() const; }; - - template struct A2; // expected-note 0-1{{template parameter is declared here}} - + + template struct A2; // expected-note 1-2{{template parameter is declared here}} + X *X_ptr; // expected-note 0-1{{declared here}} X an_X; X array_of_Xs[10]; @@ -131,16 +131,16 @@ namespace reference_parameters { S3 s3v; S3 s3cv; } - + namespace PR6250 { template void inc() { ref++; // expected-error{{read-only variable is not assignable}} } - + template void bind() { T &ref2 = ref; // expected-error{{drops 'const' qualifier}} } - + int counter; void test() { inc(); // expected-note{{instantiation of}} @@ -213,7 +213,7 @@ namespace reference_to_function { // (13.4). namespace pointer_to_member_function { struct X { }; - struct Y : X { + struct Y : X { int f(int); int g(int); int g(float); diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp index 3caed045c6688..2638bef8f20a0 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp @@ -20,39 +20,39 @@ eval> eE; // expected-error{{implicit instantiation of undefined t template< template // expected-error {{cannot be narrowed from type 'int' to 'short'}} // expected-error@-1 {{conversion from 'int' to 'void *' is not allowed in a converted constant expression}} - class TT // expected-note 2{{previous template template parameter is here}} + class TT // expected-note 2{{template parameter is declared here}} > struct X0 { }; template struct X0a; template struct X0b; template struct X0c; -template struct X0d; -template struct X0e; // expected-note{{template parameter is declared here}} +template struct X0d; // expected-note {{template parameter is declared here}} +template struct X0e; // expected-note {{template parameter is declared here}} X0 inst_x0a; X0 inst_x0b; X0 inst_x0c; -X0 inst_x0d; // expected-note {{has different template parameters}} -X0 inst_x0e; // expected-note{{template template argument has different template parameters than its corresponding template template parameter}} +X0 inst_x0d; // expected-note {{template template argument is incompatible}} +X0 inst_x0e; // expected-note {{template template argument is incompatible}} template // expected-error {{conversion from 'short' to 'void *' is not allowed in a converted constant expression}} // expected-error@-1 {{cannot be narrowed from type 'int' to 'short'}} - class TT // expected-note 2{{previous template template parameter is here}} + class TT // expected-note 2{{template parameter is declared here}} > struct X1 { }; template struct X1a; template struct X1b; template struct X1c; -template struct X1d; -template struct X1e; // expected-note{{template parameter is declared here}} +template struct X1d; // expected-note {{template parameter is declared here}} +template struct X1e; // expected-note {{template parameter is declared here}} X1 inst_x1a; X1 inst_x1b; X1 inst_x1c; X1 inst_sx1d; -X1 inst_ix1d; // expected-note {{has different template parameters}} -X1 inst_x1e; // expected-note {{has different template parameters}} +X1 inst_ix1d; // expected-note {{template template argument is incompatible}} +X1 inst_x1e; // expected-note {{template template argument is incompatible}} template class X2; // expected-note{{template is declared here}} \ // expected-note{{template is declared here}} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp index 342ffba53dbfa..5570a7f9d75de 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp @@ -13,12 +13,12 @@ template struct W { }; // #W S1 s11; S1 s12; // expected-error@-1 {{template template argument 'Y' is more constrained than template template parameter 'P'}} -// expected-note@#S1 {{'P' declared here}} +// expected-note@#S1 {{template parameter is declared here}} // expected-note@#Y {{'Y' declared here}} S1 s13; S1 s14; // expected-error@-1 {{template template argument 'W' is more constrained than template template parameter 'P'}} -// expected-note@#S1 {{'P' declared here}} +// expected-note@#S1 {{template parameter is declared here}} // expected-note@#W {{'W' declared here}} // expected-note@#F 1-2{{similar constraint expressions not considered equivalent}} // expected-note@#C 1-2{{similar constraint}} @@ -43,12 +43,12 @@ template requires C class P> struct S4 { }; // #S4 S4 s41; S4 s42; // expected-error@-1 {{template template argument 'Y' is more constrained than template template parameter 'P'}} -// expected-note@#S4 {{'P' declared here}} +// expected-note@#S4 {{template parameter is declared here}} // expected-note@#Y {{'Y' declared here}} S4 s43; S4 s44; // expected-error@-1 {{template template argument 'W' is more constrained than template template parameter 'P'}} -// expected-note@#S4 {{'P' declared here}} +// expected-note@#S4 {{template parameter is declared here}} // expected-note@#W {{'W' declared here}} template requires C typename U> struct S5 { diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp index 650f8585b115a..65f3e178ac963 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wvla %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98 -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template struct A { @@ -13,7 +13,8 @@ template struct B { }; B b; // expected-note{{instantiation of}} -template int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}} +template // #f0-temphead +int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}} enum {e}; // expected-note@-1 {{unnamed type used in template argument was declared here}} @@ -22,6 +23,7 @@ void test_f0(int n) { // #here #if __cplusplus <= 199711L // expected-warning@-2 {{template argument uses unnamed type}} // expected-note@-3 {{while substituting deduced template arguments}} + // expected-note@#f0-temphead {{template parameter is declared here}} #endif int vla[n]; // expected-warning {{variable length arrays in C++ are a Clang extension}} @@ -33,9 +35,9 @@ void test_f0(int n) { // #here } namespace N0 { - template void f0(R (*)(A1)); - template int f1(T); - template int f1(T, U); + template void f0(R (*)(A1)); // #f0 + template int f1(T); // #f1-1 + template int f1(T, U); // #f1-2 enum {e1}; #if __cplusplus <= 199711L // expected-note@-2 2{{unnamed type used in template argument was declared here}} @@ -51,7 +53,7 @@ namespace N0 { // expected-note@-2 {{unnamed type used in template argument was declared here}} #endif - template struct X; + template struct X; // cxx98-note {{template parameter is declared here}} template struct X { }; void f() { @@ -59,24 +61,28 @@ namespace N0 { #if __cplusplus <= 199711L // expected-warning@-2 {{template argument uses unnamed type}} // expected-note@-3 {{while substituting deduced template arguments}} + // expected-note@#f0 {{template parameter is declared here}} #endif &f1<__typeof__(e1)>); #if __cplusplus <= 199711L // expected-warning@-2 {{template argument uses unnamed type}} // expected-note@-3 {{while substituting explicitly-specified template arguments}} + // expected-note@#f1-1 {{template parameter is declared here}} #endif int (*fp1)(int, __typeof__(e2)) = f1; #if __cplusplus <= 199711L // expected-warning@-2 {{template argument uses unnamed type}} // expected-note@-3 {{while substituting deduced template arguments}} + // expected-note@#f1-2 {{template parameter is declared here}} #endif f1(e2); #if __cplusplus <= 199711L // expected-warning@-2 {{template argument uses unnamed type}} // expected-note@-3 {{while substituting deduced template arguments}} + // expected-note@#f1-1 {{template parameter is declared here}} #endif f1(e2); diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp index 388a80ee765c8..cf01e406c14ad 100644 --- a/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp @@ -25,7 +25,7 @@ template struct X { template static int y; // expected-error 3{{cannot be deduced}} expected-note 3{{'Inner'}} template static int y; // expected-error {{does not specialize}} - template static int z; + template static int z; // expected-note {{template parameter is declared here}} template static int z; // expected-error {{not implicitly convertible}} }; template template int X::y; // expected-error {{cannot be deduced}} expected-note {{'Inner'}} @@ -33,4 +33,4 @@ template template int X::y; // exp template<> template int X::y; // expected-error {{does not specialize}} expected-note {{instantiation of}} X xi; -X xf; // expected-note {{instantiation of}} +X xf; // expected-note 2{{instantiation of}} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp index ab4c663d24c7d..cab5c967b0c4f 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -14,10 +14,10 @@ struct is_same { }; namespace ExpandIntoFixed { - template, - typename W = V*> + template, + typename W = V*> class X0 { }; template @@ -26,24 +26,24 @@ namespace ExpandIntoFixed { typedef X0 type; }; - static_assert(is_same::type, + static_assert(is_same::type, X0, pair*>>::value, "fails with two default arguments"); - static_assert(is_same::type, + static_assert(is_same::type, X0>::value, "fails with one default argument"); - static_assert(is_same::type, + static_assert(is_same::type, X0>::value, "fails with no default arguments"); } namespace ExpandIntoFixedShifted { - template, - typename W = V*> + template, + typename W = V*> class X0 { }; template @@ -52,15 +52,15 @@ namespace ExpandIntoFixedShifted { typedef X0 type; }; - static_assert(is_same::type, + static_assert(is_same::type, X0, pair*>>::value, "fails with two default arguments"); - static_assert(is_same::type, + static_assert(is_same::type, X0>::value, "fails with one default argument"); - static_assert(is_same::type, + static_assert(is_same::type, X0>::value, "fails with no default arguments"); } @@ -76,11 +76,11 @@ namespace Deduction { } namespace PR9021a { - template + template struct A { }; template - struct B { + struct B { A a1; }; @@ -93,9 +93,9 @@ namespace PR9021b { template struct t2 { - + }; - + template class M> struct m { @@ -107,14 +107,14 @@ namespace PR9021b { } namespace PartialSpecialization { - template - struct X0; // expected-note 2{{template is declared here}} + template // expected-note {{template parameter is declared here}} + struct X0; // expected-note {{template is declared here}} template struct X0 { // expected-error {{class template partial specialization is not more specialized than the primary template}} }; - X0 x0i; // expected-error{{too few template arguments for class template 'X0'}} + X0 x0i; // expected-error{{missing template argument for template parameter}} X0 x0if; X0 x0ifd; } diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp index 30e7c65dac91c..c6e6038fb6ddf 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp @@ -48,7 +48,7 @@ namespace PacksAtDifferentLevels { int check1[X::Inner, pair, pair> - >::value == 1? 1 : -1]; + >::value == 1? 1 : -1]; template struct unsigned_tuple { }; template @@ -99,7 +99,7 @@ namespace PacksAtDifferentLevels { int check5[X2::Inner, pair, pair) - >::value == 1? 1 : -1]; + >::value == 1? 1 : -1]; template struct some_function_object { @@ -217,8 +217,8 @@ namespace ExpandingNonTypeTemplateParameters { template struct tuple_of_values { template // expected-error{{a non-type template parameter cannot have type 'float'}} \ - // expected-note{{template parameter is declared here}} - struct apply { // expected-note 2{{template is declared here}} + // expected-note 2{{template parameter is declared here}} + struct apply { // expected-note {{template is declared here}} typedef tuple...> type; }; }; @@ -236,7 +236,7 @@ namespace ExpandingNonTypeTemplateParameters { tuple_of_values::apply::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}} - tuple_of_values::apply::type tv3; // expected-error{{too few template arguments for class template 'apply'}} + tuple_of_values::apply::type tv3; // expected-error{{missing template argument for template parameter}} tuple_of_values::apply::type tv4; // expected-error{{too many template arguments for class template 'apply'}} } diff --git a/clang/test/CXX/temp/temp.deduct/p9.cpp b/clang/test/CXX/temp/temp.deduct/p9.cpp index 7b661c275211b..5f9ea27234c81 100644 --- a/clang/test/CXX/temp/temp.deduct/p9.cpp +++ b/clang/test/CXX/temp/temp.deduct/p9.cpp @@ -15,13 +15,14 @@ void test_f() { } template +// expected-note@-1 {{template parameter is declared here}} void g(T); void g(...); void test_g() { - g(0); // expected-error@-4 {{type 'int' cannot be used prior to '::'}} + g(0); // expected-error@-5 {{type 'int' cannot be used prior to '::'}} // expected-note@-4 {{in instantiation of default argument}} // expected-note@-2 {{while substituting deduced template arguments}} - // expected-note@-7 {{while substituting into a lambda expression here}} + // expected-note@-8 {{while substituting into a lambda expression here}} } template diff --git a/clang/test/CXX/temp/temp.param/p1.cpp b/clang/test/CXX/temp/temp.param/p1.cpp index e9a978961769c..e2eecdf0d4554 100644 --- a/clang/test/CXX/temp/temp.param/p1.cpp +++ b/clang/test/CXX/temp/temp.param/p1.cpp @@ -5,8 +5,9 @@ template class C> class D; // expected-error{{template template param struct A {}; -template // expected-error{{template parameter missing a default argument}} -class X0 {}; // expected-note{{template is declared here}} -X0 x0; // expected-error{{too few template arguments for class template 'X0'}} +class X0 {}; +X0 x0; // expected-error{{missing template argument for template parameter}} diff --git a/clang/test/CXX/temp/temp.param/p12.cpp b/clang/test/CXX/temp/temp.param/p12.cpp index 8317e7f24152c..e3dfb65d29461 100644 --- a/clang/test/CXX/temp/temp.param/p12.cpp +++ b/clang/test/CXX/temp/temp.param/p12.cpp @@ -32,9 +32,9 @@ template class =// expected-note {{previous template template parameter is here}} +template class =// expected-note {{template parameter is declared here}} Y1> // expected-error{{too many template arguments for class template 'Y1'}} - // expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}} + // expected-note@-1 {{template template argument is incompatible}} class C1 {}; C1<> c1; // expected-note{{while checking a default template argument}} diff --git a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp index 83144a494937b..402a205f1ea63 100644 --- a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp +++ b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp @@ -77,9 +77,9 @@ template struct wrap { template struct takedrop_impl; template struct takedrop_impl> { - template class ...Take, + template class ...Take, // expected-note 2{{template parameter is declared here}} template class ...Drop> - struct inner { // expected-note 2{{declared}} + struct inner { typedef types::type...> take; typedef types::type...> drop; }; @@ -87,11 +87,11 @@ template struct takedrop_impl> { template struct take { using type = typename takedrop_impl::type>:: - template inner::template inner...>::take; // expected-error {{too few template arguments}} + template inner::template inner...>::take; // expected-error {{missing template argument}} }; template struct drop { using type = typename takedrop_impl::type>:: - template inner::template inner...>::drop; // expected-error {{too few template arguments}} + template inner::template inner...>::drop; // expected-error {{missing template argument}} }; using T1 = take<3, int, char, double, long>::type; // expected-note {{previous}} @@ -118,7 +118,7 @@ using D3 = drop<5, int, char, double, long>::type; // expected-note {{in instant // implicitly a pack expansion. template struct DefArg { template class ...Classes> struct Inner { // expected-error {{default argument contains unexpanded parameter pack}} expected-note {{here}} - Inner(Classes<>...); // expected-error {{too few}} + Inner(Classes<>...); // expected-error {{missing template argument}} }; }; template struct vector {}; diff --git a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp index a3478c0669661..aa1666f6306d0 100644 --- a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp +++ b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp @@ -59,7 +59,7 @@ namespace ConstDestruction { f(); } - template struct Z {}; + template struct Z {}; // expected-note {{template parameter is declared here}} Z z1; Z z2; // expected-error {{non-type template argument is not a constant expression}} expected-note-re {{in call to '{{.*}}.~D()'}} } diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp index ecb82372bcb47..cb048ecdf7001 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -std=c++11 -verify=cxx11 %s // cxx11-no-diagnostics -template struct S; +template struct S; // cxx98-note {{template parameter is declared here}} template struct T { T() { diff --git a/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp b/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp index 741ebc5de41fc..749b45524f9e6 100644 --- a/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp +++ b/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp @@ -3,27 +3,27 @@ // RUN: not %clang_cc1 --std=c++1y -x c++ -fixit %t -DFIXING // RUN: %clang_cc1 --std=c++1y -x c++ %t -DFIXING -template -T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} +template // expected-note {{template parameter is declared here}} +T pi = T(3.1415926535897932385); template int pi; #ifndef FIXING -template float pi<>; // expected-error {{too few template arguments for variable template 'pi'}} +template float pi<>; // expected-error {{missing template argument for template parameter}} template double pi_var0; // expected-error {{explicit instantiation of 'pi_var0' does not refer to a function template, variable template, member function, member class, or static data member}} #endif // Should recover as if definition template double pi_var = 5; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}} #ifndef FIXING -template +template T pi0 = T(3.1415926535897932385); // expected-note {{previous definition is here}} template int pi0 = 10; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}} \ expected-error{{redefinition of 'pi0' as different kind of symbol}} #endif -template +template T pi1 = T(3.1415926535897932385); // expected-note 0-2 {{here}} // Should recover as if specialization diff --git a/clang/test/CXX/temp/temp.spec/part.spec.cpp b/clang/test/CXX/temp/temp.spec/part.spec.cpp index 4b0fdb902633a..3923d160ef5cf 100644 --- a/clang/test/CXX/temp/temp.spec/part.spec.cpp +++ b/clang/test/CXX/temp/temp.spec/part.spec.cpp @@ -250,7 +250,7 @@ template class PCT1 {}; template class PCT2 {}; template class PCT3 {}; template class PCT4 {}; -template class PCT5 {}; +template class PCT5 {}; // expected-note {{template parameter is declared here}} template class PCT6 { // expected-note@+1 3{{implicitly declared private here}} template class NPCT1 {}; @@ -416,7 +416,7 @@ template class PCTT1 {}; template class PCTT2 {}; template class PCTT3 {}; template class PCTT4 {}; -template class PCTT5 {}; +template class PCTT5 {}; // expected-note {{template parameter is declared here}} template class PCTT6 { template class NCT1 {}; template class NCT2; // forward declaration diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp index 0283dba63b110..63fd997add4ec 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp @@ -2,13 +2,13 @@ template void f(T); -template -struct A { }; // expected-note{{template is declared here}} +template // expected-note {{template parameter is declared here}} +struct A { }; struct X { template<> friend void f(int); // expected-error{{in a friend}} template<> friend class A; // expected-error{{cannot be a friend}} - + friend void f(float); // okay friend class A; // okay }; @@ -18,6 +18,6 @@ struct PR41792 { template <> friend void f<>(int); // expected-error@+2{{template specialization declaration cannot be a friend}} - // expected-error@+1{{too few template arguments for class template 'A'}} + // expected-error@+1{{missing template argument for template parameter}} template <> friend class A<>; }; diff --git a/clang/test/Misc/integer-literal-printing.cpp b/clang/test/Misc/integer-literal-printing.cpp index bd231a368fb70..bc52b3f044679 100644 --- a/clang/test/Misc/integer-literal-printing.cpp +++ b/clang/test/Misc/integer-literal-printing.cpp @@ -14,6 +14,7 @@ enum class boolTy : bool { template struct Type3Helper; template <> struct Type3Helper { typedef boolTy Ty; }; template ::Ty U> struct Type3 {}; +// expected-note@-1 {{template parameter is declared here}} // PR14386 enum class charTy : char { @@ -23,6 +24,7 @@ enum class charTy : char { template struct Type4Helper; template <> struct Type4Helper { typedef charTy Ty; }; template ::Ty U> struct Type4 {}; +// expected-note@-1 {{template parameter is declared here}} enum class scharTy : signed char { c = 0, @@ -31,6 +33,7 @@ enum class scharTy : signed char { template struct Type5Helper; template <> struct Type5Helper { typedef scharTy Ty; }; template ::Ty U> struct Type5 {}; +// expected-note@-1 {{template parameter is declared here}} enum class ucharTy : unsigned char { c = 0, @@ -39,6 +42,7 @@ enum class ucharTy : unsigned char { template struct Type6Helper; template <> struct Type6Helper { typedef ucharTy Ty; }; template ::Ty U> struct Type6 {}; +// expected-note@-1 {{template parameter is declared here}} enum class wcharTy : wchar_t { c = 0, @@ -47,6 +51,7 @@ enum class wcharTy : wchar_t { template struct Type7Helper; template <> struct Type7Helper { typedef wcharTy Ty; }; template ::Ty U> struct Type7 {}; +// expected-note@-1 {{template parameter is declared here}} enum class char16Ty : char16_t { c = 0, @@ -55,6 +60,7 @@ enum class char16Ty : char16_t { template struct Type8Helper; template <> struct Type8Helper { typedef char16Ty Ty; }; template ::Ty U> struct Type8 {}; +// expected-note@-1 {{template parameter is declared here}} enum class char32Ty : char16_t { c = 0, @@ -63,6 +69,7 @@ enum class char32Ty : char16_t { template struct Type9Helper; template <> struct Type9Helper { typedef char32Ty Ty; }; template ::Ty U> struct Type9 {}; +// expected-note@-1 {{template parameter is declared here}} void Function() { Function1(Type1<-42>()); // expected-error{{no matching function for call to 'Function1'}} diff --git a/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp b/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp index 73dff88e506b4..250b54ade0ecb 100644 --- a/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp +++ b/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp @@ -11,7 +11,7 @@ //--- mod.cppm export module mod; -template +template // expected-note 2{{template parameter is declared here}} concept ReferenceOf = Q; // expected-error@+2 {{unknown type name 'AngleIsInvalidNow'}} diff --git a/clang/test/Modules/missing-body-in-import.cpp b/clang/test/Modules/missing-body-in-import.cpp index b52ebba15087a..e25f7b5921301 100644 --- a/clang/test/Modules/missing-body-in-import.cpp +++ b/clang/test/Modules/missing-body-in-import.cpp @@ -29,6 +29,7 @@ export module mod2; import mod1; struct C: B { // expected-error {{non-type template argument is not a constant expression}} + // expected-note@mod1.cppm:11 {{template parameter is declared here}} constexpr C(int a) { } }; diff --git a/clang/test/Modules/template-default-args.cpp b/clang/test/Modules/template-default-args.cpp index 85b2a18d9e506..1d8de709fd598 100644 --- a/clang/test/Modules/template-default-args.cpp +++ b/clang/test/Modules/template-default-args.cpp @@ -22,7 +22,7 @@ template struct B; template struct C; template struct D {}; template struct F {}; -template struct G {}; +template struct G {}; // #G template struct J {}; template struct J; struct K : J<> {}; @@ -39,8 +39,10 @@ E<> e; F<> f; G<> g; // expected-error {{missing '#include "a.h"'; default argument of 'G' must be defined before it is used}} // expected-note@a.h:7 {{default argument declared here is not reachable}} +// expected-note@#G {{template parameter is declared here}} H<> h; // expected-error {{missing '#include "a.h"'; default argument of 'H' must be defined before it is used}} // expected-note@a.h:8 {{default argument declared here is not reachable}} +// expected-note@a.h:8 {{template parameter is declared here}} I<> i; L<> *l; END diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp index 9102bca8f6bb2..e47b4ef78afdf 100644 --- a/clang/test/Parser/MicrosoftExtensions.cpp +++ b/clang/test/Parser/MicrosoftExtensions.cpp @@ -126,7 +126,7 @@ void template_uuid() } -template // expected-note {{template parameter is declared here}} +template // expected-note 2{{template parameter is declared here}} class COM_CLASS_TEMPLATE { }; typedef COM_CLASS_TEMPLATE COM_TYPE_1; // expected-warning {{non-type template argument containing a dereference operation is a Microsoft extension}} diff --git a/clang/test/Parser/cxx-template-argument.cpp b/clang/test/Parser/cxx-template-argument.cpp index 3c2169f86d6e7..ffe53e7c6f77e 100644 --- a/clang/test/Parser/cxx-template-argument.cpp +++ b/clang/test/Parser/cxx-template-argument.cpp @@ -57,9 +57,9 @@ namespace PR13210 { // Don't emit spurious messages namespace pr16225add { - template struct Known { }; // expected-note 3 {{template is declared here}} + template struct Known { }; // expected-note 3{{template parameter is declared here}} template struct X; - template struct ABC; // expected-note {{template is declared here}} + template struct ABC; // expected-note {{template parameter is declared here}} template struct ABC2 {}; template struct foo : @@ -68,7 +68,7 @@ namespace pr16225add { template struct foo2 : UnknownBase, // expected-error {{no template named 'UnknownBase'}} - Known // expected-error {{too few template arguments for class template 'Known'}} + Known // expected-error {{missing template argument for template parameter}} { }; template struct foo3 : @@ -76,8 +76,8 @@ namespace pr16225add { { }; template struct foo4 : - UnknownBase >, // expected-error {{too few template arguments for class template 'ABC'}} - Known // expected-error {{too few template arguments for class template 'Known'}} + UnknownBase >, // expected-error {{missing template argument for template parameter}} + Known // expected-error {{missing template argument for template parameter}} { }; template struct foo5 : @@ -92,7 +92,7 @@ namespace pr16225add { #if __cplusplus <= 199711L // expected-error@-2 {{use '> >'}} #endif - Known // expected-error {{too few template arguments for class template 'Known'}} + Known // expected-error {{missing template argument for template parameter}} { }; template struct foo7 : diff --git a/clang/test/Parser/cxx-template-template-recovery.cpp b/clang/test/Parser/cxx-template-template-recovery.cpp index 5700b160cd364..2ece5a8ccdbea 100644 --- a/clang/test/Parser/cxx-template-template-recovery.cpp +++ b/clang/test/Parser/cxx-template-template-recovery.cpp @@ -1,33 +1,33 @@ // RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only %s namespace a { - template - concept C1 = true; // #C1 + template // #C1-T + concept C1 = true; template auto V1 = true; // #V1 namespace b { - template - concept C2 = true; // #C2 + template // #C2-T + concept C2 = true; template auto V2 = true; // #V2 } } -template -concept C3 = true; // #C3 +template // #C3-T +concept C3 = true; template auto V3 = true; // #V3 template