diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6dfb2d7195203..e0ac3af7b98e3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4933,6 +4933,8 @@ def err_template_param_shadow : Error< def ext_template_param_shadow : ExtWarn< err_template_param_shadow.Summary>, InGroup; def note_template_param_here : Note<"template parameter is declared here">; +def note_template_param_external : Note< + "template parameter from hidden source: %0">; def warn_template_export_unsupported : Warning< "exported templates are unsupported">; def err_template_outside_namespace_or_class_scope : Error< @@ -5061,6 +5063,8 @@ def err_template_arg_list_different_arity : Error< "%select{class template|function template|variable template|alias template|" "template template parameter|concept|template}1 %2">; def note_template_decl_here : Note<"template is declared here">; +def note_template_decl_external : Note< + "template declaration from hidden source: %0">; def err_template_arg_must_be_type : Error< "template argument for template type parameter must be a type">; def err_template_arg_must_be_type_suggest : Error< diff --git a/clang/include/clang/Sema/HLSLExternalSemaSource.h b/clang/include/clang/Sema/HLSLExternalSemaSource.h index 4b6bc96f72e22..c0bfff327139f 100644 --- a/clang/include/clang/Sema/HLSLExternalSemaSource.h +++ b/clang/include/clang/Sema/HLSLExternalSemaSource.h @@ -30,9 +30,9 @@ class HLSLExternalSemaSource : public ExternalSemaSource { void defineHLSLVectorAlias(); void defineTrivialHLSLTypes(); - void forwardDeclareHLSLTypes(); + void defineHLSLTypesWithForwardDeclarations(); - void completeBufferType(CXXRecordDecl *Record); + void onCompletion(CXXRecordDecl *Record, CompletionFunction Fn); public: ~HLSLExternalSemaSource() override; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6de1a098e067a..a4912e3625c38 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8557,6 +8557,10 @@ class Sema final { TemplateParameterList *Params, TemplateArgumentLoc &Arg); + void NoteTemplateLocation(const NamedDecl &Decl, + std::optional ParamRange = {}); + void NoteTemplateParameterLocation(const NamedDecl &Decl); + ExprResult BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, QualType ParamType, diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 8de144486c91d..8ed6480a9f5c9 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -306,6 +306,7 @@ struct BuiltinTypeDeclBuilder { } TemplateParameterListBuilder addTemplateArgumentList(); + BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef Names); }; struct TemplateParameterListBuilder { @@ -360,11 +361,19 @@ struct TemplateParameterListBuilder { return Builder; } }; +} // namespace TemplateParameterListBuilder BuiltinTypeDeclBuilder::addTemplateArgumentList() { return TemplateParameterListBuilder(*this); } -} // namespace + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef Names) { + TemplateParameterListBuilder Builder = this->addTemplateArgumentList(); + for (StringRef Name : Names) + Builder.addTypeParameter(Name); + return Builder.finalizeTemplateArgs(); +} HLSLExternalSemaSource::~HLSLExternalSemaSource() {} @@ -390,7 +399,7 @@ void HLSLExternalSemaSource::InitializeSema(Sema &S) { // Force external decls in the HLSL namespace to load from the PCH. (void)HLSLNamespace->getCanonicalDecl()->decls_begin(); defineTrivialHLSLTypes(); - forwardDeclareHLSLTypes(); + defineHLSLTypesWithForwardDeclarations(); // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's // built in types inside a namespace, but we are planning to change that in @@ -467,18 +476,32 @@ void HLSLExternalSemaSource::defineTrivialHLSLTypes() { .Record; } -void HLSLExternalSemaSource::forwardDeclareHLSLTypes() { +/// Set up common members and attributes for buffer types +static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, + ResourceClass RC, + ResourceKind RK) { + return BuiltinTypeDeclBuilder(Decl) + .addHandleMember() + .addDefaultHandleConstructor(S, RC) + .annotateResourceClass(RC, RK); +} + +void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { CXXRecordDecl *Decl; Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") - .addTemplateArgumentList() - .addTypeParameter("element_type", SemaPtr->getASTContext().FloatTy) - .finalizeTemplateArgs() + .addSimpleTemplateParams({"element_type"}) .Record; - if (!Decl->isCompleteDefinition()) - Completions.insert( - std::make_pair(Decl->getCanonicalDecl(), - std::bind(&HLSLExternalSemaSource::completeBufferType, - this, std::placeholders::_1))); + onCompletion(Decl, [this](CXXRecordDecl *Decl) { + setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, + ResourceKind::TypedBuffer) + .addArraySubscriptOperators() + .completeDefinition(); + }); +} + +void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record, + CompletionFunction Fn) { + Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn)); } void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) { @@ -496,12 +519,3 @@ void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) { return; It->second(Record); } - -void HLSLExternalSemaSource::completeBufferType(CXXRecordDecl *Record) { - BuiltinTypeDeclBuilder(Record) - .addHandleMember() - .addDefaultHandleConstructor(*SemaPtr, ResourceClass::UAV) - .addArraySubscriptOperators() - .annotateResourceClass(ResourceClass::UAV, ResourceKind::TypedBuffer) - .completeDefinition(); -} diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c0d21ec330acf..e6d4655644c62 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5971,7 +5971,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { diag::err_deduction_guide_name_not_class_template) << (int)getTemplateNameKindForDiagnostics(TN) << TN; if (Template) - Diag(Template->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*Template); return DeclarationNameInfo(); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7385eac48d8c8..bece54b4bfa14 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11462,7 +11462,7 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, GuidedTemplateDecl->getDeclContext()->getRedeclContext())) { Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope) << GuidedTemplateDecl; - Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*GuidedTemplateDecl); } auto &DS = D.getMutableDeclSpec(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 50ee0a5acb558..042ca61abe44d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10573,7 +10573,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( diag::err_deduced_non_class_template_specialization_type) << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName; if (auto *TD = TemplateName.getAsTemplateDecl()) - Diag(TD->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*TD); return QualType(); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index ca09b0481bcac..4cc87c9fa765c 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1444,7 +1444,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, for (const auto &Capture : Intro.Captures) { if (Capture.Id == TP->getIdentifier()) { Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id; - Diag(TP->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*TP); } } } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 34d7b8c731e90..be9e294a72f31 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -820,7 +820,6 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) return true; - std::optional Note; QualType InstantiationTy; if (TagDecl *TD = dyn_cast(Instantiation)) InstantiationTy = Context.getTypeDeclType(TD); @@ -838,25 +837,25 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) << /*member function*/ 1 << Instantiation->getDeclName() << Instantiation->getDeclContext(); - Note = diag::note_explicit_instantiation_here; + Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here); } else { assert(isa(Instantiation) && "Must be a TagDecl!"); Diag(PointOfInstantiation, diag::err_implicit_instantiate_member_undefined) << InstantiationTy; - Note = diag::note_member_declared_at; + Diag(Pattern->getLocation(), diag::note_member_declared_at); } } else { if (isa(Instantiation)) { Diag(PointOfInstantiation, diag::err_explicit_instantiation_undefined_func_template) << Pattern; - Note = diag::note_explicit_instantiation_here; + Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here); } else if (isa(Instantiation)) { Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) << (TSK != TSK_ImplicitInstantiation) << InstantiationTy; - Note = diag::note_template_decl_here; + NoteTemplateLocation(*Pattern); } else { assert(isa(Instantiation) && "Must be a VarDecl!"); if (isa(Instantiation)) { @@ -869,11 +868,9 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) << /*static data member*/ 2 << Instantiation->getDeclName() << Instantiation->getDeclContext(); - Note = diag::note_explicit_instantiation_here; + Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here); } } - if (Note) // Diagnostics were emitted. - Diag(Pattern->getLocation(), *Note); // In general, Instantiation isn't marked invalid to get more than one // error for multiple undefined instantiations. But the code that does @@ -898,8 +895,9 @@ void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { // Make this a warning when MSVC compatibility is requested. unsigned DiagId = getLangOpts().MSVCCompat ? diag::ext_template_param_shadow : diag::err_template_param_shadow; - Diag(Loc, DiagId) << cast(PrevDecl)->getDeclName(); - Diag(PrevDecl->getLocation(), diag::note_template_param_here); + NamedDecl *ND = cast(PrevDecl); + Diag(Loc, DiagId) << ND->getDeclName(); + NoteTemplateParameterLocation(*ND); } /// AdjustDeclIfTemplate - If the given decl happens to be a template, reset @@ -4488,7 +4486,7 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) { << SFINAEArgString; } - S.Diag(Template->getLocation(), diag::note_template_decl_here); + S.NoteTemplateLocation(*Template); SmallVector PartialAC, TemplateAC; Template->getAssociatedConstraints(TemplateAC); Partial->getAssociatedConstraints(PartialAC); @@ -4966,8 +4964,7 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name, Diag(Loc, diag::err_template_missing_args) << (int)getTemplateNameKindForDiagnostics(Name) << Name; if (TemplateDecl *TD = Name.getAsTemplateDecl()) { - Diag(TD->getLocation(), diag::note_template_decl_here) - << TD->getTemplateParameters()->getSourceRange(); + NoteTemplateLocation(*TD, TD->getTemplateParameters()->getSourceRange()); } } @@ -5319,7 +5316,7 @@ bool Sema::CheckTemplateTypeArgument( ? diag::ext_ms_template_type_arg_missing_typename : diag::err_template_arg_must_be_type_suggest) << FixItHint::CreateInsertion(Loc, "typename "); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); // Recover by synthesizing a type using the location information that we // already have. @@ -5348,7 +5345,7 @@ bool Sema::CheckTemplateTypeArgument( // is not a type. SourceRange SR = AL.getSourceRange(); Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR; - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return true; } @@ -5794,8 +5791,8 @@ bool Sema::CheckTemplateArgument( // therefore cannot be a non-type template argument. Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr) << Arg.getSourceRange(); + NoteTemplateParameterLocation(*Param); - Diag(Param->getLocation(), diag::note_template_param_here); return true; case TemplateArgument::Type: { @@ -5815,7 +5812,7 @@ bool Sema::CheckTemplateArgument( Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T; else Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return true; } @@ -5936,8 +5933,7 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, << /*not enough args*/0 << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD; - S.Diag(TD->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); + S.NoteTemplateLocation(*TD, Params->getSourceRange()); return true; } @@ -6003,8 +5999,7 @@ bool Sema::CheckTemplateArgumentList( << /*not enough args*/0 << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template; - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); + NoteTemplateLocation(*Template, Params->getSourceRange()); return true; } } @@ -6036,7 +6031,7 @@ bool Sema::CheckTemplateArgumentList( diag::err_template_expansion_into_fixed_list) << (isa(Template) ? 1 : 0) << NewArgs[ArgIdx].getSourceRange(); - Diag((*Param)->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(**Param); return true; } @@ -6232,8 +6227,7 @@ bool Sema::CheckTemplateArgumentList( << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc()); - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); + NoteTemplateLocation(*Template, Params->getSourceRange()); return true; } @@ -6645,7 +6639,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, for (unsigned I = 0, N = Notes.size(); I != N; ++I) S.Diag(Notes[I].first, Notes[I].second); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_Error; } @@ -6671,7 +6665,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // 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.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_NullPointer; } @@ -6681,7 +6675,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // message with the information we have here. S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid) << EvalResult.Val.getAsString(S.Context, ParamType); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_Error; } @@ -6693,7 +6687,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code) << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()), ")"); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_NullPointer; } @@ -6734,7 +6728,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( S.Diag(Arg->getBeginLoc(), diag::err_template_arg_ref_bind_ignores_quals) << ParamType << Arg->getType() << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6752,7 +6746,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( else S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) << ArgIn->getType() << ParamType << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6895,7 +6889,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!Entity) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -6903,7 +6897,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (isa(Entity) || isa(Entity)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field) << Entity << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -6912,7 +6906,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!Method->isStatic()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method) << Method << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6952,7 +6946,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (Var->getType()->isReferenceType()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var) << Var->getType() << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -6973,14 +6967,14 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( ParamType.getNonReferenceType())) { S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) << ParamType << FixItHint::CreateRemoval(AddrOpLoc); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); ArgType = Entity->getType(); } @@ -7002,14 +6996,14 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); } } @@ -7125,7 +7119,7 @@ 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.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -7237,7 +7231,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } } @@ -7247,7 +7241,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // where the parameter type is deduced. ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc()); if (ParamType.isNull()) { - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } } @@ -7283,7 +7277,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) << Arg->getType() << ParamType.getUnqualifiedType(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } @@ -7548,7 +7542,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (!ArgType->isIntegralOrEnumerationType()) { Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } else if (!Arg->isValueDependent()) { class TmplArgICEDiagnoser : public VerifyICEDiagnoser { @@ -7586,7 +7580,7 @@ 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(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } @@ -7632,7 +7626,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative) << toString(OldValue, 10) << toString(Value, 10) << Param->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); } // Complain if we overflowed the template parameter's type. @@ -7647,7 +7641,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large) << toString(OldValue, 10) << toString(Value, 10) << Param->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); } } @@ -7774,7 +7768,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, case NPV_NotNullPointer: Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible) << Arg->getType() << ParamType; - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); case NPV_Error: @@ -7909,6 +7903,37 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, Arg.getLocation()); } +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> Str; + llvm::raw_svector_ostream Out(Str); + PrintingPolicy PP = S.getPrintingPolicy(); + PP.TerseOutput = 1; + Decl.print(Out, PP); + return S.Diag(Decl.getLocation(), ExternalDiagID) << Out.str(); +} + +void Sema::NoteTemplateLocation(const NamedDecl &Decl, + std::optional ParamRange) { + SemaDiagnosticBuilder DB = + noteLocation(*this, Decl, diag::note_template_decl_here, + diag::note_template_decl_external); + if (ParamRange && ParamRange->isValid()) { + assert(Decl.getLocation().isValid() && + "Parameter range has location when Decl does not"); + DB << *ParamRange; + } +} + +void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { + noteLocation(*this, Decl, diag::note_template_param_here, + diag::note_template_param_external); +} + /// Given a non-type template argument that refers to a /// declaration and the type of its corresponding non-type template /// parameter, produce an expression that properly refers to that @@ -8634,9 +8659,7 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs( S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(), diag::err_dependent_typed_non_type_arg_in_partial_spec) << Param->getType(); - S.Diag(Param->getLocation(), diag::note_template_param_here) - << (IsDefaultArgument ? ParamUseRange : SourceRange()) - << ParamUseRange; + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -11216,7 +11239,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, else Diag(IILoc, diag::err_deduced_tst) << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)); - Diag(TD->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*TD); return QualType(); } return Context.getElaboratedType( diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 56d133f20a293..83610503ed9b1 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3792,7 +3792,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, << Kind << Error << (int)SemaRef.getTemplateNameKindForDiagnostics(TN) << QualType(Deduced, 0) << AutoRange; if (auto *TD = TN.getAsTemplateDecl()) - SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here); + SemaRef.NoteTemplateLocation(*TD); T = SemaRef.Context.IntTy; D.setInvalidType(true); diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl index 9dd9244b73eed..c1613520a146c 100644 --- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl @@ -13,8 +13,6 @@ // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RWBuffer // EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type -// EMPTY-NEXT: TemplateArgument type 'float' -// EMPTY-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -33,8 +31,6 @@ RWBuffer Buffer; // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RWBuffer // CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type -// CHECK-NEXT: TemplateArgument type 'float' -// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final diff --git a/clang/test/AST/HLSL/pch.hlsl b/clang/test/AST/HLSL/pch.hlsl index 74254fedf27cb..27fae8f499daa 100644 --- a/clang/test/AST/HLSL/pch.hlsl +++ b/clang/test/AST/HLSL/pch.hlsl @@ -6,7 +6,7 @@ // Make sure PCH works by using function declared in PCH header and declare a RWBuffer in current file. // CHECK:FunctionDecl 0x[[FOO:[0-9a-f]+]] <{{.*}}:2:1, line:4:1> line:2:8 imported used foo 'float2 (float2, float2)' -// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:10:1, col:23> col:23 Buffer 'hlsl::RWBuffer':'hlsl::RWBuffer<>' +// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:10:1, col:23> col:23 Buffer 'hlsl::RWBuffer' hlsl::RWBuffer Buffer; float2 bar(float2 a, float2 b) { diff --git a/clang/test/AST/HLSL/pch_with_buf.hlsl b/clang/test/AST/HLSL/pch_with_buf.hlsl index 4e657606cbcb1..e8eae533af629 100644 --- a/clang/test/AST/HLSL/pch_with_buf.hlsl +++ b/clang/test/AST/HLSL/pch_with_buf.hlsl @@ -5,9 +5,9 @@ // Make sure PCH works by using function declared in PCH header. // CHECK:FunctionDecl 0x[[FOO:[0-9a-f]+]] <{{.*}}:2:1, line:4:1> line:2:8 imported used foo 'float2 (float2, float2)' // Make sure buffer defined in PCH works. -// CHECK:VarDecl 0x{{[0-9a-f]+}} col:17 imported Buf 'RWBuffer':'hlsl::RWBuffer<>' +// CHECK:VarDecl 0x{{[0-9a-f]+}} col:17 imported Buf 'RWBuffer' // Make sure declare a RWBuffer in current file works. -// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:11:1, col:23> col:23 Buf2 'hlsl::RWBuffer':'hlsl::RWBuffer<>' +// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:11:1, col:23> col:23 Buf2 'hlsl::RWBuffer' hlsl::RWBuffer Buf2; float2 bar(float2 a, float2 b) { diff --git a/clang/test/AST/HLSL/resource_binding_attr.hlsl b/clang/test/AST/HLSL/resource_binding_attr.hlsl index 6836071971111..71900f2dbda55 100644 --- a/clang/test/AST/HLSL/resource_binding_attr.hlsl +++ b/clang/test/AST/HLSL/resource_binding_attr.hlsl @@ -23,15 +23,15 @@ float foo() { return a + b; } -// CHECK: VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV 'RWBuffer':'hlsl::RWBuffer<>' callinit -// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer<>' 'void ()' +// CHECK: VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV 'RWBuffer':'hlsl::RWBuffer' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer' 'void ()' // CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} "u3" "space0" RWBuffer UAV : register(u3); -// CHECK: -VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV1 'RWBuffer':'hlsl::RWBuffer<>' callinit -// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer<>' 'void ()' +// CHECK: -VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV1 'RWBuffer':'hlsl::RWBuffer' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer' 'void ()' // CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} "u2" "space0" -// CHECK-NEXT:-VarDecl 0x{{[0-9a-f]+}} col:38 UAV2 'RWBuffer':'hlsl::RWBuffer<>' callinit -// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer<>' 'void ()' +// CHECK-NEXT:-VarDecl 0x{{[0-9a-f]+}} col:38 UAV2 'RWBuffer':'hlsl::RWBuffer' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer' 'void ()' // CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} "u4" "space0" RWBuffer UAV1 : register(u2), UAV2 : register(u4); diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl index a9f6567aa00b8..7e79ae3bf005f 100644 --- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl @@ -5,6 +5,14 @@ typedef vector float3; RWBuffer Buffer; +// expected-error@+2 {{class template 'RWBuffer' requires template arguments}} +// expected-note@*:* {{template declaration from hidden source: template class RWBuffer final}} +RWBuffer BufferErr1; + +// expected-error@+2 {{too few template arguments for class template 'RWBuffer'}} +// expected-note@*:* {{template declaration from hidden source: template class RWBuffer final}} +RWBuffer<> BufferErr2; + [numthreads(1,1,1)] void main() { (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::RWBuffer'}} diff --git a/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl index d2598a57400b0..6aedb9304ed93 100644 --- a/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl @@ -2,17 +2,16 @@ // Some bad declarations hlsl::vector ShouldWorkSomeday; // expected-error{{use of alias template 'hlsl::vector' requires template arguments}} +// expected-note@*:* {{template declaration from hidden source: template using vector = element __attribute__((ext_vector_type(element_count)))}} hlsl::vector<1> BadVec; // expected-error{{template argument for template type parameter must be a type}} -// expected-note@*:* {{template is declared here}} -// expected-note@*:* {{template parameter is declared here}} - +// expected-note@*:* {{template parameter from hidden source: class element = float}} hlsl::vector AnotherBadVec; // expected-error{{template argument for non-type template parameter must be an expression}} -// expected-note@*:* {{template parameter is declared here}} +// expected-note@*:* {{template parameter from hidden source: int element_count = 4}} hlsl::vector YABV; // expected-error{{too many template arguments for alias template 'vector'}} -// expected-note@*:* {{template is declared here}} +// expected-note@*:* {{template declaration from hidden source: template using vector = element __attribute__((ext_vector_type(element_count)))}} // This code is rejected by clang because clang puts the HLSL built-in types // into the HLSL namespace.