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

Reply via email to