From 3cb6ead77c6668fcd1362763b2603752c6c595fa Mon Sep 17 00:00:00 2001
From: Eric Li
Date: Tue, 2 May 2023 13:59:46 -0400
Subject: [PATCH] [clang][TypePrinter] Add option to skip over elaborated types
Elaborated types are sugar that represent how the type was spelled in
the original source. When printing a type outside of that original
context, the qualifiers as saved in the elaborated type will be
incorrect. Additionally, their existence also inhibits the use of
`PrintingCallbacks::isScopeVisible` as a customization point.
Differential Revision: https://reviews.llvm.org/D149677
---
clang/include/clang/AST/PrettyPrinter.h | 15 ++++++++++-----
clang/lib/AST/TypePrinter.cpp | 11 +++++++++++
clang/unittests/AST/TypePrinterTest.cpp | 27 +++++++++++++++++++++++++++
3 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 5aeaca7b..8a0bc6d 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -60,14 +60,15 @@ struct PrintingPolicy {
: Indentation(2), SuppressSpecifiers(false),
SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
SuppressScope(false), SuppressUnwrittenScope(false),
- SuppressInlineNamespace(true), SuppressInitializers(false),
- ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
- SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
+ SuppressInlineNamespace(true), SuppressElaboration(false),
+ SuppressInitializers(false), ConstantArraySizeAsWritten(false),
+ AnonymousTagLocations(true), SuppressStrongLifetime(false),
+ SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false),
SuppressDefaultTemplateArgs(true), Bool(LO.Bool),
Nullptr(LO.CPlusPlus11 || LO.C2x), NullptrTypeInNamespace(LO.CPlusPlus),
- Restrict(LO.C99), Alignof(LO.CPlusPlus11),
- UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus),
+ Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
+ UseVoidForZeroParams(!LO.CPlusPlus),
SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
PolishForDeclaration(false), Half(LO.Half),
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
@@ -139,6 +140,10 @@ struct PrintingPolicy {
/// removed.
unsigned SuppressInlineNamespace : 1;
+ /// Ignore qualifiers and tag keywords as specified by elaborated type sugar,
+ /// instead letting the underlying type print as normal.
+ unsigned SuppressElaboration : 1;
+
/// Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 00f5fe0..1b62f66 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1576,6 +1576,11 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
return;
}
+ if (Policy.SuppressElaboration) {
+ printBefore(T->getNamedType(), OS);
+ return;
+ }
+
// The tag definition will take care of these.
if (!Policy.IncludeTagDefinition)
{
@@ -1595,6 +1600,12 @@ void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
raw_ostream &OS) {
if (Policy.IncludeTagDefinition && T->getOwnedTagDecl())
return;
+
+ if (Policy.SuppressElaboration) {
+ printAfter(T->getNamedType(), OS);
+ return;
+ }
+
ElaboratedTypePolicyRAII PolicyRAII(Policy);
printAfter(T->getNamedType(), OS);
}
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index 77ff442..f0a6eb7 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -97,6 +97,33 @@ TEST(TypePrinter, ParamsUglified) {
"const f *", Clean));
}
+TEST(TypePrinter, SuppressElaboration) {
+ llvm::StringLiteral Code = R"cpp(
+ namespace shared {
+ namespace a {
+ template
+ struct S {};
+ } // namespace a
+ namespace b {
+ struct Foo {};
+ } // namespace b
+ using Alias = a::S;
+ } // namespace shared
+ )cpp";
+
+ auto Matcher = typedefNameDecl(hasName("::shared::Alias"),
+ hasType(qualType().bind("id")));
+ ASSERT_TRUE(PrintedTypeMatches(
+ Code, {}, Matcher, "a::S",
+ [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; }));
+ ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher,
+ "shared::a::S",
+ [](PrintingPolicy &Policy) {
+ Policy.SuppressElaboration = true;
+ Policy.FullyQualifiedName = true;
+ }));
+}
+
TEST(TypePrinter, TemplateIdWithNTTP) {
constexpr char Code[] = R"cpp(
template
--
2.7.4