On Mon, Nov 16, 2020 at 7:24 PM Richard Smith <rich...@metafoo.co.uk> wrote: > > On Mon, 16 Nov 2020 at 18:49, David Blaikie <dblai...@gmail.com> wrote: >> >> On Wed, Nov 11, 2020 at 3:08 PM Richard Smith via cfe-commits >> <cfe-commits@lists.llvm.org> wrote: >> > >> > >> > Author: Richard Smith >> > Date: 2020-11-11T15:05:51-08:00 >> > New Revision: e7f3e2103cdb567dda4fd52f81bf4bc07179f5a8 >> > >> > URL: >> > https://github.com/llvm/llvm-project/commit/e7f3e2103cdb567dda4fd52f81bf4bc07179f5a8 >> > DIFF: >> > https://github.com/llvm/llvm-project/commit/e7f3e2103cdb567dda4fd52f81bf4bc07179f5a8.diff >> > >> > LOG: Suppress printing template arguments that match default template >> > arguments of types by default. >> > >> > This somewhat improves the worst-case printing of types like >> > std::string, std::vector, etc., where many irrelevant default arguments >> > can be included in the type as printed if we've lost the type sugar. >> >> "somewhat" - are there still some remaining challenges here? (I'd have >> thought this would be a significant improvement in these worst cases >> of lost type sugar) > > > For std::vector, std::map, etc. we now print these types as-expected. But... > > std::string is now printed as std::basic_string<char>, which, while an > improvement, is still not the type name that we know a user would really want > to see (similarly for std::string_view, and really any of the typedefs for > std::basic_*). https://reviews.llvm.org/D91311 has a fix for that, but we're > still in discussion as to whether that's the right interface for that > functionality.
Ah, fair point for sure! thanks for the details and pointer to the review/discussion. >> > Added: >> > clang/test/Misc/diag-template.cpp >> > >> > Modified: >> > clang/include/clang/AST/PrettyPrinter.h >> > clang/include/clang/AST/Type.h >> > clang/lib/AST/DeclTemplate.cpp >> > clang/lib/AST/TypePrinter.cpp >> > clang/lib/Frontend/FrontendActions.cpp >> > clang/test/SemaCXX/cxx14-compat.cpp >> > clang/test/SemaCXX/generic-selection.cpp >> > clang/test/SemaTemplate/class-template-id.cpp >> > clang/test/SemaTemplate/class-template-spec.cpp >> > clang/test/SemaTemplate/instantiation-default-1.cpp >> > >> > Removed: >> > >> > >> > >> > ################################################################################ >> > diff --git a/clang/include/clang/AST/PrettyPrinter.h >> > b/clang/include/clang/AST/PrettyPrinter.h >> > index dfd5851bb30d..50e2142e2ef0 100644 >> > --- a/clang/include/clang/AST/PrettyPrinter.h >> > +++ b/clang/include/clang/AST/PrettyPrinter.h >> > @@ -55,7 +55,8 @@ struct PrintingPolicy { >> > SuppressInitializers(false), ConstantArraySizeAsWritten(false), >> > AnonymousTagLocations(true), SuppressStrongLifetime(false), >> > SuppressLifetimeQualifiers(false), >> > - SuppressTemplateArgsInCXXConstructors(false), Bool(LO.Bool), >> > + SuppressTemplateArgsInCXXConstructors(false), >> > + SuppressDefaultTemplateArgs(true), Bool(LO.Bool), >> > Nullptr(LO.CPlusPlus11), Restrict(LO.C99), >> > Alignof(LO.CPlusPlus11), >> > UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus), >> > SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), >> > @@ -167,6 +168,10 @@ struct PrintingPolicy { >> > /// constructors. >> > unsigned SuppressTemplateArgsInCXXConstructors : 1; >> > >> > + /// When true, attempt to suppress template arguments that match the >> > default >> > + /// argument for the parameter. >> > + unsigned SuppressDefaultTemplateArgs : 1; >> > + >> > /// Whether we can use 'bool' rather than '_Bool' (even if the language >> > /// doesn't actually have 'bool', because, e.g., it is defined as a >> > macro). >> > unsigned Bool : 1; >> > >> > diff --git a/clang/include/clang/AST/Type.h >> > b/clang/include/clang/AST/Type.h >> > index 1442bc740620..6dedd097ff89 100644 >> > --- a/clang/include/clang/AST/Type.h >> > +++ b/clang/include/clang/AST/Type.h >> > @@ -61,6 +61,7 @@ class ExtQuals; >> > class QualType; >> > class ConceptDecl; >> > class TagDecl; >> > +class TemplateParameterList; >> > class Type; >> > >> > enum { >> > @@ -5196,15 +5197,18 @@ class alignas(8) TemplateSpecializationType >> > /// enclosing the template arguments. >> > void printTemplateArgumentList(raw_ostream &OS, >> > ArrayRef<TemplateArgument> Args, >> > - const PrintingPolicy &Policy); >> > + const PrintingPolicy &Policy, >> > + const TemplateParameterList *TPL = >> > nullptr); >> > >> > void printTemplateArgumentList(raw_ostream &OS, >> > ArrayRef<TemplateArgumentLoc> Args, >> > - const PrintingPolicy &Policy); >> > + const PrintingPolicy &Policy, >> > + const TemplateParameterList *TPL = >> > nullptr); >> > >> > void printTemplateArgumentList(raw_ostream &OS, >> > const TemplateArgumentListInfo &Args, >> > - const PrintingPolicy &Policy); >> > + const PrintingPolicy &Policy, >> > + const TemplateParameterList *TPL = >> > nullptr); >> > >> > /// The injected class name of a C++ class template or class >> > /// template partial specialization. Used to record that a type was >> > >> > diff --git a/clang/lib/AST/DeclTemplate.cpp >> > b/clang/lib/AST/DeclTemplate.cpp >> > index 9918377070c3..328ceaa63df3 100644 >> > --- a/clang/lib/AST/DeclTemplate.cpp >> > +++ b/clang/lib/AST/DeclTemplate.cpp >> > @@ -914,10 +914,14 @@ void >> > ClassTemplateSpecializationDecl::getNameForDiagnostic( >> > const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this); >> > if (const ASTTemplateArgumentListInfo *ArgsAsWritten = >> > PS ? PS->getTemplateArgsAsWritten() : nullptr) { >> > - printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); >> > + printTemplateArgumentList( >> > + OS, ArgsAsWritten->arguments(), Policy, >> > + getSpecializedTemplate()->getTemplateParameters()); >> > } else { >> > const TemplateArgumentList &TemplateArgs = getTemplateArgs(); >> > - printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); >> > + printTemplateArgumentList( >> > + OS, TemplateArgs.asArray(), Policy, >> > + getSpecializedTemplate()->getTemplateParameters()); >> > } >> > } >> > >> > @@ -1261,10 +1265,14 @@ void >> > VarTemplateSpecializationDecl::getNameForDiagnostic( >> > const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this); >> > if (const ASTTemplateArgumentListInfo *ArgsAsWritten = >> > PS ? PS->getTemplateArgsAsWritten() : nullptr) { >> > - printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); >> > + printTemplateArgumentList( >> > + OS, ArgsAsWritten->arguments(), Policy, >> > + getSpecializedTemplate()->getTemplateParameters()); >> > } else { >> > const TemplateArgumentList &TemplateArgs = getTemplateArgs(); >> > - printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); >> > + printTemplateArgumentList( >> > + OS, TemplateArgs.asArray(), Policy, >> > + getSpecializedTemplate()->getTemplateParameters()); >> > } >> > } >> > >> > >> > diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp >> > index 5e9b22664185..3368905007a4 100644 >> > --- a/clang/lib/AST/TypePrinter.cpp >> > +++ b/clang/lib/AST/TypePrinter.cpp >> > @@ -1124,7 +1124,9 @@ void TypePrinter::printAutoBefore(const AutoType *T, >> > raw_ostream &OS) { >> > OS << T->getTypeConstraintConcept()->getName(); >> > auto Args = T->getTypeConstraintArguments(); >> > if (!Args.empty()) >> > - printTemplateArgumentList(OS, Args, Policy); >> > + printTemplateArgumentList( >> > + OS, Args, Policy, >> > + T->getTypeConstraintConcept()->getTemplateParameters()); >> > OS << ' '; >> > } >> > switch (T->getKeyword()) { >> > @@ -1226,7 +1228,9 @@ void TypePrinter::AppendScope(DeclContext *DC, >> > raw_ostream &OS) { >> > IncludeStrongLifetimeRAII Strong(Policy); >> > OS << Spec->getIdentifier()->getName(); >> > const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); >> > - printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); >> > + printTemplateArgumentList( >> > + OS, TemplateArgs.asArray(), Policy, >> > + Spec->getSpecializedTemplate()->getTemplateParameters()); >> > OS << "::"; >> > } else if (const auto *Tag = dyn_cast<TagDecl>(DC)) { >> > if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) >> > @@ -1317,7 +1321,9 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream >> > &OS) { >> > Args = TemplateArgs.asArray(); >> > } >> > IncludeStrongLifetimeRAII Strong(Policy); >> > - printTemplateArgumentList(OS, Args, Policy); >> > + printTemplateArgumentList( >> > + OS, Args, Policy, >> > + Spec->getSpecializedTemplate()->getTemplateParameters()); >> > } >> > >> > spaceBeforePlaceHolder(OS); >> > @@ -1389,7 +1395,11 @@ void TypePrinter::printTemplateSpecializationBefore( >> > IncludeStrongLifetimeRAII Strong(Policy); >> > T->getTemplateName().print(OS, Policy); >> > >> > - printTemplateArgumentList(OS, T->template_arguments(), Policy); >> > + const TemplateParameterList *TPL = nullptr; >> > + if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) >> > + TPL = TD->getTemplateParameters(); >> > + >> > + printTemplateArgumentList(OS, T->template_arguments(), Policy, TPL); >> > spaceBeforePlaceHolder(OS); >> > } >> > >> > @@ -1789,9 +1799,159 @@ static void printArgument(const >> > TemplateArgumentLoc &A, >> > return A.getArgument().print(PP, OS); >> > } >> > >> > +static bool isSubstitutedTemplateArgument(ASTContext &Ctx, >> > TemplateArgument Arg, >> > + TemplateArgument Pattern, >> > + ArrayRef<TemplateArgument> Args, >> > + unsigned Depth); >> > + >> > +static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType >> > Pattern, >> > + ArrayRef<TemplateArgument> Args, unsigned >> > Depth) { >> > + if (Ctx.hasSameType(T, Pattern)) >> > + return true; >> > + >> > + // A type parameter matches its argument. >> > + if (auto *TTPT = Pattern->getAs<TemplateTypeParmType>()) { >> > + if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() && >> > + Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) { >> > + QualType SubstArg = Ctx.getQualifiedType( >> > + Args[TTPT->getIndex()].getAsType(), Pattern.getQualifiers()); >> > + return Ctx.hasSameType(SubstArg, T); >> > + } >> > + return false; >> > + } >> > + >> > + // FIXME: Recurse into array types. >> > + >> > + // All other cases will need the types to be identically qualified. >> > + Qualifiers TQual, PatQual; >> > + T = Ctx.getUnqualifiedArrayType(T, TQual); >> > + Pattern = Ctx.getUnqualifiedArrayType(Pattern, PatQual); >> > + if (TQual != PatQual) >> > + return false; >> > + >> > + // Recurse into pointer-like types. >> > + { >> > + QualType TPointee = T->getPointeeType(); >> > + QualType PPointee = Pattern->getPointeeType(); >> > + if (!TPointee.isNull() && !PPointee.isNull()) >> > + return T->getTypeClass() == Pattern->getTypeClass() && >> > + isSubstitutedType(Ctx, TPointee, PPointee, Args, Depth); >> > + } >> > + >> > + // Recurse into template specialization types. >> > + if (auto *PTST = >> > + >> > Pattern.getCanonicalType()->getAs<TemplateSpecializationType>()) { >> > + TemplateName Template; >> > + ArrayRef<TemplateArgument> TemplateArgs; >> > + if (auto *TTST = T->getAs<TemplateSpecializationType>()) { >> > + Template = TTST->getTemplateName(); >> > + TemplateArgs = TTST->template_arguments(); >> > + } else if (auto *CTSD = >> > dyn_cast_or_null<ClassTemplateSpecializationDecl>( >> > + T->getAsCXXRecordDecl())) { >> > + Template = TemplateName(CTSD->getSpecializedTemplate()); >> > + TemplateArgs = CTSD->getTemplateArgs().asArray(); >> > + } else { >> > + return false; >> > + } >> > + >> > + if (!isSubstitutedTemplateArgument(Ctx, Template, >> > PTST->getTemplateName(), >> > + Args, Depth)) >> > + return false; >> > + if (TemplateArgs.size() != PTST->getNumArgs()) >> > + return false; >> > + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) >> > + if (!isSubstitutedTemplateArgument(Ctx, TemplateArgs[I], >> > PTST->getArg(I), >> > + Args, Depth)) >> > + return false; >> > + return true; >> > + } >> > + >> > + // FIXME: Handle more cases. >> > + return false; >> > +} >> > + >> > +static bool isSubstitutedTemplateArgument(ASTContext &Ctx, >> > TemplateArgument Arg, >> > + TemplateArgument Pattern, >> > + ArrayRef<TemplateArgument> Args, >> > + unsigned Depth) { >> > + Arg = Ctx.getCanonicalTemplateArgument(Arg); >> > + Pattern = Ctx.getCanonicalTemplateArgument(Pattern); >> > + if (Arg.structurallyEquals(Pattern)) >> > + return true; >> > + >> > + if (Pattern.getKind() == TemplateArgument::Expression) { >> > + if (auto *DRE = >> > + >> > dyn_cast<DeclRefExpr>(Pattern.getAsExpr()->IgnoreParenImpCasts())) { >> > + if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) >> > + return NTTP->getDepth() == Depth && Args.size() > >> > NTTP->getIndex() && >> > + Args[NTTP->getIndex()].structurallyEquals(Arg); >> > + } >> > + } >> > + >> > + if (Arg.getKind() != Pattern.getKind()) >> > + return false; >> > + >> > + if (Arg.getKind() == TemplateArgument::Type) >> > + return isSubstitutedType(Ctx, Arg.getAsType(), Pattern.getAsType(), >> > Args, >> > + Depth); >> > + >> > + if (Arg.getKind() == TemplateArgument::Template) { >> > + TemplateDecl *PatTD = Pattern.getAsTemplate().getAsTemplateDecl(); >> > + if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(PatTD)) >> > + return TTPD->getDepth() == Depth && Args.size() > TTPD->getIndex() >> > && >> > + Ctx.getCanonicalTemplateArgument(Args[TTPD->getIndex()]) >> > + .structurallyEquals(Arg); >> > + } >> > + >> > + // FIXME: Handle more cases. >> > + return false; >> > +} >> > + >> > +/// Make a best-effort determination of whether the type T can be >> > produced by >> > +/// substituting Args into the default argument of Param. >> > +static bool isSubstitutedDefaultArgument(ASTContext &Ctx, >> > TemplateArgument Arg, >> > + const NamedDecl *Param, >> > + ArrayRef<TemplateArgument> Args, >> > + unsigned Depth) { >> > + // An empty pack is equivalent to not providing a pack argument. >> > + if (Arg.getKind() == TemplateArgument::Pack && Arg.pack_size() == 0) >> > + return true; >> > + >> > + if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Param)) { >> > + return TTPD->hasDefaultArgument() && >> > + isSubstitutedTemplateArgument(Ctx, Arg, >> > TTPD->getDefaultArgument(), >> > + Args, Depth); >> > + } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { >> > + return TTPD->hasDefaultArgument() && >> > + isSubstitutedTemplateArgument( >> > + Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, >> > Depth); >> > + } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Param)) { >> > + return NTTPD->hasDefaultArgument() && >> > + isSubstitutedTemplateArgument(Ctx, Arg, >> > NTTPD->getDefaultArgument(), >> > + Args, Depth); >> > + } >> > + return false; >> > +} >> > + >> > template<typename TA> >> > static void printTo(raw_ostream &OS, ArrayRef<TA> Args, >> > - const PrintingPolicy &Policy, bool SkipBrackets) { >> > + const PrintingPolicy &Policy, bool SkipBrackets, >> > + const TemplateParameterList *TPL) { >> > + // Drop trailing template arguments that match default arguments. >> > + if (TPL && Policy.SuppressDefaultTemplateArgs && >> > + !Policy.PrintCanonicalTypes && !Args.empty() && >> > + Args.size() <= TPL->size()) { >> > + ASTContext &Ctx = TPL->getParam(0)->getASTContext(); >> > + llvm::SmallVector<TemplateArgument, 8> OrigArgs; >> > + for (const TA &A : Args) >> > + OrigArgs.push_back(getArgument(A)); >> > + while (!Args.empty() && >> > + isSubstitutedDefaultArgument(Ctx, getArgument(Args.back()), >> > + TPL->getParam(Args.size() - 1), >> > + OrigArgs, TPL->getDepth())) >> > + Args = Args.drop_back(); >> > + } >> > + >> > const char *Comma = Policy.MSVCFormatting ? "," : ", "; >> > if (!SkipBrackets) >> > OS << '<'; >> > @@ -1806,7 +1966,7 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> >> > Args, >> > if (Argument.getKind() == TemplateArgument::Pack) { >> > if (Argument.pack_size() && !FirstArg) >> > OS << Comma; >> > - printTo(ArgOS, Argument.getPackAsArray(), Policy, true); >> > + printTo(ArgOS, Argument.getPackAsArray(), Policy, true, nullptr); >> > } else { >> > if (!FirstArg) >> > OS << Comma; >> > @@ -1839,20 +1999,23 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> >> > Args, >> > >> > void clang::printTemplateArgumentList(raw_ostream &OS, >> > const TemplateArgumentListInfo >> > &Args, >> > - const PrintingPolicy &Policy) { >> > - return printTo(OS, Args.arguments(), Policy, false); >> > + const PrintingPolicy &Policy, >> > + const TemplateParameterList *TPL) { >> > + printTemplateArgumentList(OS, Args.arguments(), Policy, TPL); >> > } >> > >> > void clang::printTemplateArgumentList(raw_ostream &OS, >> > ArrayRef<TemplateArgument> Args, >> > - const PrintingPolicy &Policy) { >> > - printTo(OS, Args, Policy, false); >> > + const PrintingPolicy &Policy, >> > + const TemplateParameterList *TPL) { >> > + printTo(OS, Args, Policy, false, TPL); >> > } >> > >> > void clang::printTemplateArgumentList(raw_ostream &OS, >> > ArrayRef<TemplateArgumentLoc> Args, >> > - const PrintingPolicy &Policy) { >> > - printTo(OS, Args, Policy, false); >> > + const PrintingPolicy &Policy, >> > + const TemplateParameterList *TPL) { >> > + printTo(OS, Args, Policy, false, TPL); >> > } >> > >> > std::string Qualifiers::getAsString() const { >> > >> > diff --git a/clang/lib/Frontend/FrontendActions.cpp >> > b/clang/lib/Frontend/FrontendActions.cpp >> > index 0993e5eb033f..f38da54cebcc 100644 >> > --- a/clang/lib/Frontend/FrontendActions.cpp >> > +++ b/clang/lib/Frontend/FrontendActions.cpp >> > @@ -467,7 +467,10 @@ class DefaultTemplateInstCallback : public >> > TemplateInstantiationCallback { >> > Entry.Event = BeginInstantiation ? "Begin" : "End"; >> > if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) { >> > llvm::raw_string_ostream OS(Entry.Name); >> > - NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), >> > true); >> > + PrintingPolicy Policy = TheSema.Context.getPrintingPolicy(); >> > + // FIXME: Also ask for FullyQualifiedNames? >> > + Policy.SuppressDefaultTemplateArgs = false; >> > + NamedTemplate->getNameForDiagnostic(OS, Policy, true); >> > const PresumedLoc DefLoc = >> > >> > TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation()); >> > if(!DefLoc.isInvalid()) >> > >> > diff --git a/clang/test/Misc/diag-template.cpp >> > b/clang/test/Misc/diag-template.cpp >> > new file mode 100644 >> > index 000000000000..30d4829409bb >> > --- /dev/null >> > +++ b/clang/test/Misc/diag-template.cpp >> > @@ -0,0 +1,37 @@ >> > +// RUN: %clang_cc1 -verify %s >> > + >> > +namespace default_args { >> > + template<typename T> struct char_traits; >> > + template<typename T> struct allocator; >> > + template<typename T, typename = char_traits<T>, typename = >> > allocator<T>> struct basic_string {}; >> > + >> > + typedef basic_string<char> string; >> > + >> > + template<typename T> T f(T); >> > + >> > + void test1() { >> > + string s; >> > + f(s).size(); // expected-error {{no member named 'size' in >> > 'default_args::basic_string<char>'}} >> > + } >> > + >> > + template<typename T> struct default_delete {}; >> > + template<class T, class Deleter = default_delete<T>> class unique_ptr >> > {}; >> > + template<class T, class Deleter> class unique_ptr<T[], Deleter> {}; >> > + void test2() { >> > + unique_ptr<string> ups; >> > + f(ups).reset(); // expected-error {{no member named 'reset' in >> > 'default_args::unique_ptr<default_args::basic_string<char>>'}} >> > + } >> > + >> > + template<int A, int B = A> struct Z { int error[B]; }; // >> > expected-error {{negative size}} >> > + Z<-1> z; // expected-note {{in instantiation of template class >> > 'default_args::Z<-1>' requested here}} >> > + >> > + template<template<typename> class A = allocator, template<typename> >> > class B = A> struct Q {}; >> > + void test3() { >> > + f(Q<>()).g(); // expected-error {{no member named 'g' in >> > 'default_args::Q<>'}} >> > + f(Q<allocator>()).g(); // expected-error {{no member named 'g' in >> > 'default_args::Q<>'}} >> > + f(Q<allocator, allocator>()).g(); // expected-error {{no member named >> > 'g' in 'default_args::Q<>'}} >> > + f(Q<char_traits>()).g(); // expected-error {{no member named 'g' in >> > 'default_args::Q<char_traits>'}} >> > + f(Q<char_traits, char_traits>()).g(); // expected-error {{no member >> > named 'g' in 'default_args::Q<char_traits>'}} >> > + f(Q<char_traits, allocator>()).g(); // expected-error {{no member >> > named 'g' in 'default_args::Q<char_traits, allocator>'}} >> > + } >> > +} >> > >> > diff --git a/clang/test/SemaCXX/cxx14-compat.cpp >> > b/clang/test/SemaCXX/cxx14-compat.cpp >> > index d70f477cd09a..d6396a7de4df 100644 >> > --- a/clang/test/SemaCXX/cxx14-compat.cpp >> > +++ b/clang/test/SemaCXX/cxx14-compat.cpp >> > @@ -16,7 +16,7 @@ namespace [[]] NS_with_attr {} // expected-warning >> > {{incompatible with C++ stand >> > enum { e [[]] }; // expected-warning {{incompatible with C++ standards >> > before C++17}} >> > >> > template<typename T = int> struct X {}; >> > -X x; // expected-warning {{class template argument deduction is >> > incompatible with C++ standards before C++17; for compatibility, use >> > explicit type name 'X<int>'}} >> > +X x; // expected-warning {{class template argument deduction is >> > incompatible with C++ standards before C++17; for compatibility, use >> > explicit type name 'X<>'}} >> > >> > template<template<typename> class> struct Y {}; >> > Y<X> yx; // ok, not class template argument deduction >> > >> > diff --git a/clang/test/SemaCXX/generic-selection.cpp >> > b/clang/test/SemaCXX/generic-selection.cpp >> > index c0a5d89fff67..8bf4a784f9bf 100644 >> > --- a/clang/test/SemaCXX/generic-selection.cpp >> > +++ b/clang/test/SemaCXX/generic-selection.cpp >> > @@ -14,7 +14,7 @@ static_assert(A<int>::id == 1, "fail"); >> > static_assert(A<float>::id == 2, "fail"); >> > static_assert(A<double, double>::id == 3, "fail"); >> > >> > -A<char> a1; // expected-note {{in instantiation of template class >> > 'A<char, void *>' requested here}} >> > +A<char> a1; // expected-note {{in instantiation of template class >> > 'A<char>' requested here}} >> > A<short, int> a2; // expected-note {{in instantiation of template class >> > 'A<short, int>' requested here}} >> > >> > template <typename T, typename U> >> > >> > diff --git a/clang/test/SemaTemplate/class-template-id.cpp >> > b/clang/test/SemaTemplate/class-template-id.cpp >> > index 50cb3ef59ea4..b32a03e478d9 100644 >> > --- a/clang/test/SemaTemplate/class-template-id.cpp >> > +++ b/clang/test/SemaTemplate/class-template-id.cpp >> > @@ -9,9 +9,9 @@ A<int, FLOAT> *foo(A<int> *ptr, A<int> const *ptr2, A<int, >> > double> *ptr3) { >> > if (ptr) >> > return ptr; // okay >> > else if (ptr2) >> > - return ptr2; // expected-error{{cannot initialize return object of >> > type 'A<int, FLOAT> *' (aka 'A<int, float> *') with an lvalue of type >> > 'const A<int> *'}} >> > + return ptr2; // expected-error{{cannot initialize return object of >> > type 'A<int> *' with an lvalue of type 'const A<int> *'}} >> > else { >> > - return ptr3; // expected-error{{cannot initialize return object of >> > type 'A<int, FLOAT> *' (aka 'A<int, float> *') with an lvalue of type >> > 'A<int, double> *'}} >> > + return ptr3; // expected-error{{cannot initialize return object of >> > type 'A<int> *' with an lvalue of type 'A<int, double> *'}} >> > } >> > } >> > >> > >> > diff --git a/clang/test/SemaTemplate/class-template-spec.cpp >> > b/clang/test/SemaTemplate/class-template-spec.cpp >> > index d763944371cc..e96ef44b7a25 100644 >> > --- a/clang/test/SemaTemplate/class-template-spec.cpp >> > +++ b/clang/test/SemaTemplate/class-template-spec.cpp >> > @@ -22,7 +22,7 @@ int test_incomplete_specs(A<double, double> *a1, >> > A<double> *a2) >> > { >> > (void)a1->x; // expected-error{{member access into incomplete type}} >> > - (void)a2->x; // expected-error{{implicit instantiation of undefined >> > template 'A<double, int>'}} >> > + (void)a2->x; // expected-error{{implicit instantiation of undefined >> > template 'A<double>'}} >> > } >> > >> > typedef float FLOAT; >> > >> > diff --git a/clang/test/SemaTemplate/instantiation-default-1.cpp >> > b/clang/test/SemaTemplate/instantiation-default-1.cpp >> > index ab9eca75e239..33e01b6b8aa5 100644 >> > --- a/clang/test/SemaTemplate/instantiation-default-1.cpp >> > +++ b/clang/test/SemaTemplate/instantiation-default-1.cpp >> > @@ -36,7 +36,7 @@ typedef int& int_ref_t; >> > Def2<int_ref_t> *d2; // expected-note{{in instantiation of default >> > argument for 'Def2<int &>' required here}} >> > >> > >> > -template<> struct Def1<const int> { }; // expected-error{{redefinition of >> > 'Def1<const int, const int>'}} >> > +template<> struct Def1<const int> { }; // expected-error{{redefinition of >> > 'Def1<const int>'}} >> > >> > template<typename T, typename T2 = T&> struct Def3; >> > >> > >> > >> > >> > _______________________________________________ >> > cfe-commits mailing list >> > cfe-commits@lists.llvm.org >> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits