diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -1567,7 +1567,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Name = "foo"; - HI.Type = "cls > >"; + HI.Type = "cls>>"; HI.Value = "{}"; }}, { @@ -1579,7 +1579,7 @@ HI.Definition = "template <> struct cls>> {}"; HI.Kind = index::SymbolKind::Struct; HI.NamespaceScope = ""; - HI.Name = "cls > >"; + HI.Name = "cls>>"; HI.Documentation = "type of nested templates."; }}, { diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp @@ -247,19 +247,19 @@ typedef TwoArgTemplate >, S<(0 < 0), Q > > Nested_t; // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' -// CHECK-FIXES: using Nested_t = TwoArgTemplate >, S<(0 < 0), Q > >; +// CHECK-FIXES: using Nested_t = TwoArgTemplate>, S<(0 < 0), Q>>; template class Variadic {}; typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t; // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' -// CHECK-FIXES: using Variadic_t = Variadic >, S<(0 < 0), Variadic > > > +// CHECK-FIXES: using Variadic_t = Variadic>, S<(0 < 0), Variadic>>> typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t, *Variadic_p; // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' // CHECK-MESSAGES: :[[@LINE-2]]:103: warning: use 'using' instead of 'typedef' -// CHECK-FIXES: using Variadic_t = Variadic >, S<(0 < 0), Variadic > > >; +// CHECK-FIXES: using Variadic_t = Variadic>, S<(0 < 0), Variadic>>>; // CHECK-FIXES-NEXT: using Variadic_p = Variadic_t*; typedef struct { int a; } R_t, *R_p; diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -57,7 +57,8 @@ SuppressLifetimeQualifiers(false), SuppressTemplateArgsInCXXConstructors(false), Bool(LO.Bool), Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), - UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false), + UseVoidForZeroParams(!LO.CPlusPlus), + SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), @@ -183,6 +184,9 @@ /// with zero parameters. unsigned UseVoidForZeroParams : 1; + /// Whether nested templates must be closed like a > rather than a>. + unsigned SplitTemplateClosers : 1; + /// Provide a 'terse' output. /// /// For example, in this mode we don't print function bodies, class members, diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1722,13 +1722,13 @@ OS << ArgString; - NeedSpace = (!ArgString.empty() && ArgString.back() == '>'); + // If the last character of our string is '>', add another space to + // keep the two '>''s separate tokens. + NeedSpace = Policy.SplitTemplateClosers && !ArgString.empty() && + ArgString.back() == '>'; FirstArg = false; } - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. if (NeedSpace) OS << ' '; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -63,7 +63,7 @@ // expected-error@-1 {{typename specifier refers to non-type member 'type' in 'D'}} using r1i5 = r1>; // expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = invalid]}} -// expected-note@-2 {{while checking constraint satisfaction for template 'r1 >' required here}} +// expected-note@-2 {{while checking constraint satisfaction for template 'r1>' required here}} // mismatching template arguments @@ -191,4 +191,4 @@ using c2 = C1_check; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = std_example::has_type]}} using c3 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}} using c4 = C3_check; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}} -} \ No newline at end of file +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp --- a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp @@ -13,9 +13,9 @@ eval> eA; eval> eB; -eval> eC; // expected-error{{implicit instantiation of undefined template 'eval >'}} -eval> eD; // expected-error{{implicit instantiation of undefined template 'eval >'}} -eval> eE; // expected-error{{implicit instantiation of undefined template 'eval >}} +eval> eC; // expected-error{{implicit instantiation of undefined template 'eval>'}} +eval> eD; // expected-error{{implicit instantiation of undefined template 'eval>'}} +eval> eE; // expected-error{{implicit instantiation of undefined template 'eval>}} template