[clang] e7f3e21 - Suppress printing template arguments that match default template

David Blaikie via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 16 19:39:14 PST 2020


On Mon, Nov 16, 2020 at 7:24 PM Richard Smith <richard at metafoo.co.uk> wrote:
>
> 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.

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 at lists.llvm.org
>> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list