Fully qualify template template parameters when printing
I discovered this quirk when working on some DWARF - AST printing prints type template parameters fully qualified, but printed template template parameters the way they were written syntactically, or wholely unqualified - instead, we should print them consistently with the way we print type template parameters: fully qualified. The one place this got weird was for partial specializations like in ast-print-temp-class.cpp - hence the need for checking for TemplateNameDependenceScope::DependentInstantiation template template parameters. (not 100% sure that's the right solution to that, though - open to ideas) Differential Revision: https://reviews.llvm.org/D108794
This commit is contained in:
parent
cf53c6c971
commit
5fb3f43778
|
@ -295,7 +295,7 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
|
|||
}
|
||||
std::string getDetail(const TemplateName &TN) {
|
||||
return toString([&](raw_ostream &OS) {
|
||||
TN.print(OS, Ctx.getPrintingPolicy(), /*SuppressNNS=*/true);
|
||||
TN.print(OS, Ctx.getPrintingPolicy(), TemplateName::Qualified::None);
|
||||
});
|
||||
}
|
||||
std::string getDetail(const Attr *A) {
|
||||
|
|
|
@ -309,16 +309,17 @@ public:
|
|||
/// unexpanded parameter pack (for C++0x variadic templates).
|
||||
bool containsUnexpandedParameterPack() const;
|
||||
|
||||
enum class Qualified { None, AsWritten, Fully };
|
||||
/// Print the template name.
|
||||
///
|
||||
/// \param OS the output stream to which the template name will be
|
||||
/// printed.
|
||||
///
|
||||
/// \param SuppressNNS if true, don't print the
|
||||
/// nested-name-specifier that precedes the template name (if it has
|
||||
/// one).
|
||||
/// \param Qual print the (Qualified::None) simple name,
|
||||
/// (Qualified::AsWritten) any written (possibly partial) qualifier, or
|
||||
/// (Qualified::Fully) the fully qualified name.
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool SuppressNNS = false) const;
|
||||
Qualified Qual = Qualified::AsWritten) const;
|
||||
|
||||
/// Debugging aid that dumps the template name.
|
||||
void dump(raw_ostream &OS) const;
|
||||
|
|
|
@ -311,7 +311,8 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
|||
= dyn_cast<TemplateSpecializationType>(T)) {
|
||||
// Print the template name without its corresponding
|
||||
// nested-name-specifier.
|
||||
SpecType->getTemplateName().print(OS, InnerPolicy, true);
|
||||
SpecType->getTemplateName().print(OS, InnerPolicy,
|
||||
TemplateName::Qualified::None);
|
||||
|
||||
// Print the template argument list.
|
||||
printTemplateArgumentList(OS, SpecType->template_arguments(),
|
||||
|
|
|
@ -452,7 +452,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
|
|||
break;
|
||||
|
||||
case Template:
|
||||
getAsTemplate().print(Out, Policy);
|
||||
getAsTemplate().print(Out, Policy, TemplateName::Qualified::Fully);
|
||||
break;
|
||||
|
||||
case TemplateExpansion:
|
||||
|
|
|
@ -220,19 +220,28 @@ bool TemplateName::containsUnexpandedParameterPack() const {
|
|||
return getDependence() & TemplateNameDependence::UnexpandedPack;
|
||||
}
|
||||
|
||||
void
|
||||
TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool SuppressNNS) const {
|
||||
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
Qualified Qual) const {
|
||||
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
|
||||
OS << *Template;
|
||||
if (Qual == Qualified::Fully &&
|
||||
getDependence() != TemplateNameDependenceScope::DependentInstantiation)
|
||||
Template->printQualifiedName(OS, Policy);
|
||||
else
|
||||
OS << *Template;
|
||||
else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
|
||||
if (!SuppressNNS)
|
||||
if (Qual == Qualified::Fully &&
|
||||
getDependence() !=
|
||||
TemplateNameDependenceScope::DependentInstantiation) {
|
||||
QTN->getTemplateDecl()->printQualifiedName(OS, Policy);
|
||||
return;
|
||||
}
|
||||
if (Qual == Qualified::AsWritten)
|
||||
QTN->getQualifier()->print(OS, Policy);
|
||||
if (QTN->hasTemplateKeyword())
|
||||
OS << "template ";
|
||||
OS << *QTN->getDecl();
|
||||
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
|
||||
if (!SuppressNNS && DTN->getQualifier())
|
||||
if (Qual == Qualified::AsWritten && DTN->getQualifier())
|
||||
DTN->getQualifier()->print(OS, Policy);
|
||||
OS << "template ";
|
||||
|
||||
|
@ -242,7 +251,7 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
|||
OS << "operator " << getOperatorSpelling(DTN->getOperator());
|
||||
} else if (SubstTemplateTemplateParmStorage *subst
|
||||
= getAsSubstTemplateTemplateParm()) {
|
||||
subst->getReplacement().print(OS, Policy, SuppressNNS);
|
||||
subst->getReplacement().print(OS, Policy, Qual);
|
||||
} else if (SubstTemplateTemplateParmPackStorage *SubstPack
|
||||
= getAsSubstTemplateTemplateParmPack())
|
||||
OS << *SubstPack->getParameterPack();
|
||||
|
|
|
@ -1226,7 +1226,8 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
|
|||
|
||||
SmallString<128> NS;
|
||||
llvm::raw_svector_ostream OS(NS);
|
||||
Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false);
|
||||
Ty->getTemplateName().print(OS, getPrintingPolicy(),
|
||||
TemplateName::Qualified::None);
|
||||
printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy());
|
||||
|
||||
SourceLocation Loc = AliasDecl->getLocation();
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace dr1004 { // dr1004: 5
|
|||
template<typename> struct B1 {};
|
||||
template<template<typename> class> struct B2 {};
|
||||
template<typename X> void f(); // expected-note {{[with X = dr1004::A<int>]}}
|
||||
template<template<typename> class X> void f(); // expected-note {{[with X = A]}}
|
||||
template<template<typename> class X> void g(); // expected-note {{[with X = A]}}
|
||||
template<template<typename> class X> void f(); // expected-note {{[with X = dr1004::A]}}
|
||||
template<template<typename> class X> void g(); // expected-note {{[with X = dr1004::A]}}
|
||||
template<typename X> void g(); // expected-note {{[with X = dr1004::A<int>]}}
|
||||
struct C : A<int> {
|
||||
B1<A> b1a;
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace DeduceNonTypeTemplateArgsInArray {
|
|||
}
|
||||
|
||||
namespace DeduceWithDefaultArgs {
|
||||
template<template<typename...> class Container> void f(Container<int>); // expected-note {{deduced type 'X<[...], (default) int>' of 1st parameter does not match adjusted type 'X<[...], double>' of argument [with Container = X]}}
|
||||
template<template<typename...> class Container> void f(Container<int>); // expected-note {{deduced type 'X<[...], (default) int>' of 1st parameter does not match adjusted type 'X<[...], double>' of argument [with Container = DeduceWithDefaultArgs::X]}}
|
||||
template<typename, typename = int> struct X {};
|
||||
void g() {
|
||||
// OK, use default argument for the second template parameter.
|
||||
|
|
|
@ -132,7 +132,7 @@ inline namespace InlineNS {}
|
|||
// CHECK: TypedefDecl=OtherType:26:18 (Definition) [type=outer::inner::Bar::OtherType] [typekind=Typedef] [canonicaltype=double] [canonicaltypekind=Double] [isPOD=1]
|
||||
// CHECK: TypedefDecl=ArrayType:27:15 (Definition) [type=outer::inner::Bar::ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]
|
||||
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
|
||||
// CHECK: FieldDecl=baz:28:20 (Definition) [type=Baz<int, 1, Foo>] [typekind=Unexposed] [templateargs/3= [type=int] [typekind=Int]] [canonicaltype=outer::Baz<int, 1, Foo>] [canonicaltypekind=Record] [canonicaltemplateargs/3= [type=int] [typekind=Int]] [isPOD=1]
|
||||
// CHECK: FieldDecl=baz:28:20 (Definition) [type=Baz<int, 1, outer::Foo>] [typekind=Unexposed] [templateargs/3= [type=int] [typekind=Int]] [canonicaltype=outer::Baz<int, 1, outer::Foo>] [canonicaltypekind=Record] [canonicaltemplateargs/3= [type=int] [typekind=Int]] [isPOD=1]
|
||||
// CHECK: TemplateRef=Baz:9:8 [type=] [typekind=Invalid] [isPOD=0]
|
||||
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
|
||||
// CHECK: TemplateRef=Foo:4:8 [type=] [typekind=Invalid] [isPOD=0]
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace default_args {
|
|||
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>'}}
|
||||
f(Q<char_traits>()).g(); // expected-error {{no member named 'g' in 'default_args::Q<default_args::char_traits>'}}
|
||||
f(Q<char_traits, char_traits>()).g(); // expected-error {{no member named 'g' in 'default_args::Q<default_args::char_traits>'}}
|
||||
f(Q<char_traits, allocator>()).g(); // expected-error {{no member named 'g' in 'default_args::Q<default_args::char_traits, default_args::allocator>'}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace N {
|
|||
0 << a.const_ref(); // expected-error{{invalid operands to binary expression ('int' and 'X<int>')}}
|
||||
}
|
||||
|
||||
void f0( Y<int,1> y){ 1 << y; } // expected-note{{in instantiation of function template specialization 'N::operator<<<Y, int, 1>' requested here}}
|
||||
void f0( Y<int,1> y){ 1 << y; } // expected-note{{in instantiation of function template specialization 'N::operator<<<N::Y, int, 1>' requested here}}
|
||||
}
|
||||
|
||||
// PR12179
|
||||
|
|
Loading…
Reference in a new issue