[clang] e7f3e21 - Suppress printing template arguments that match default template
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 16 19:24:44 PST 2020
On Mon, 16 Nov 2020 at 18:49, David Blaikie <dblaikie at gmail.com> wrote:
> On Wed, Nov 11, 2020 at 3:08 PM Richard Smith via cfe-commits
> <cfe-commits at 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.
> >
> > 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 at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201116/3508f402/attachment-0001.html>
More information about the cfe-commits
mailing list