Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AST] Only dump desugared type when visibly different #65214

Merged
merged 1 commit into from
Oct 26, 2023

Conversation

jrtc27
Copy link
Collaborator

@jrtc27 jrtc27 commented Sep 2, 2023

These are an artifact of how types are structured but serve little
purpose, merely showing that the type is sugared in some way. For
example, ElaboratedType's existence means struct S gets printed as
'struct S':'struct S' in the AST, which is unnecessary visual clutter.
Note that skipping the second print when the types have the same string
matches what we do for diagnostics, where the aka will be skipped.

@jrtc27 jrtc27 requested review from a team as code owners September 2, 2023 22:04
@jrtc27 jrtc27 requested review from AaronBallman and removed request for a team September 2, 2023 22:04
jrtc27 added a commit to CTSRD-CHERI/llvm-project that referenced this pull request Sep 2, 2023
We need a new type like DependentPointerType for non-dependent contexts
that can track __capability applied to things like typeof(...) in order
to have a corresponding TypeLoc for the qualifier, otherwise things like
TypeSpecLocFiller get out of sync and, in some cases assert (in other
cases silently use the wrong DeclSpec). However, this then exposes the
fact TypePrinter's PrintingPolicy's SuppressCapabilityQualifier isn't
always able to be set to the right value (e.g. when printing out a
reinterpret_cast<T> to the user, or when dumping the AST), and so we end
up with redundant __capability qualifiers appearing for purecap code in
some cases, and so we need to track alongside the pointer interpretation
whether it was explicit (which also needs care to ensure it doesn't mess
with canonicalisation). Whilst the output is now noisier in cases where
__capability is used in purecap code, this is more faithful to the
source.

The churn in the AST output due to __capability in the source always
being sugar is an unfortunate side-effect, but this should disappear
if llvm/llvm-project#65214 is merged.

Fixes #710
@philnik777 philnik777 added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label Sep 3, 2023
@cor3ntin
Copy link
Contributor

cor3ntin commented Sep 3, 2023

These are an artifact of how types are structured but serve little
purpose, merely showing that the type is sugared in some way. For
example, ElaboratedType's existence means struct S gets printed as
'struct S':'struct S' in the AST, which is unnecessary visual clutter.
Note that skipping the second print when the types have the same string
matches what we do for diagnostics, where the aka will be skipped.

There seems to be some words missing on the last line of the commit message / description.

Otherwise, the direction of the change looks reasonable to me.
We are still working through some bugs with CI, I'll take a longer look when that's fixed.

Comment on lines +323 to +327
if (DSQT != SQT) {
std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
if (DSQTS != SQTS)
Ret["desugaredQualType"] = DSQTS;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make the argument that it make sense for json to have both.
Not having it slightly complicate the logic of consumer code.

I think we need to decide to either:

  • keep it
  • document the change in a ReleaseNotes entry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the issue for consumer code? It already needs to handle non-sugar types. And it's not like the type in the JSON is a structured representation of the QualType, it's just a textual dump, so you'd have to go and re-parse it to do anything with it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aim with the original code was "if the desugared type and the given qual type are the same thing, only print one if we've been asked to print desugared", and this keeps that same aim, so I think this is reasonable.

That said, I agree with @cor3ntin that this needs a release note because there is a change in behavior that may break downstream consumers who expect the desugaredQualType field that's no longer going to show up for them. I don't expect it to be significantly disruptive in practice, but we should explicitly communicate that sort of change to users.

Comment on lines 684 to 685
// If the type is sugared, also dump a (shallow) desugared type when
// visibly different.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If the type is sugared, also dump a (shallow) desugared type when
// visibly different.
// If the type is sugared, also dump a (shallow) desugared type when
// it is visibly different.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with what's there? It's grammatically correct AFAIK.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either approach is grammatically correct, this seems likely to be more about readability for ESL folks. I'm slightly in favor of the change, but don't have a strong opinion (If @cor3ntin thinks it helps readability for him, I think we should make the change -- he's French)

@jrtc27
Copy link
Collaborator Author

jrtc27 commented Sep 3, 2023

These are an artifact of how types are structured but serve little
purpose, merely showing that the type is sugared in some way. For
example, ElaboratedType's existence means struct S gets printed as
'struct S':'struct S' in the AST, which is unnecessary visual clutter.
Note that skipping the second print when the types have the same string
matches what we do for diagnostics, where the aka will be skipped.

There seems to be some words missing on the last line of the commit message / description.

I don't think so? What's there is what I intended to write.

jrtc27 added a commit to CTSRD-CHERI/llvm-project that referenced this pull request Sep 4, 2023
We need a new type like DependentPointerType for non-dependent contexts
that can track __capability applied to things like typeof(...) in order
to have a corresponding TypeLoc for the qualifier, otherwise things like
TypeSpecLocFiller get out of sync and, in some cases assert (in other
cases silently use the wrong DeclSpec). However, this then exposes the
fact TypePrinter's PrintingPolicy's SuppressCapabilityQualifier isn't
always able to be set to the right value (e.g. when printing out a
reinterpret_cast<T> to the user, or when dumping the AST), and so we end
up with redundant __capability qualifiers appearing for purecap code in
some cases, and so we need to track alongside the pointer interpretation
whether it was explicit (which also needs care to ensure it doesn't mess
with canonicalisation). Whilst the output is now noisier in cases where
__capability is used in purecap code, this is more faithful to the
source.

The churn in the AST output due to __capability in the source always
being sugar is an unfortunate side-effect, but this should disappear
if llvm/llvm-project#65214 is merged.

Fixes #710
@shafik
Copy link
Collaborator

shafik commented Sep 5, 2023

So it looks like some of these changes undo some of the change introduced by @mizvekov in some tests. Maybe @zygoloid or @AaronBallman has some more input here.

@jrtc27
Copy link
Collaborator Author

jrtc27 commented Sep 5, 2023

So it looks like some of these changes undo some of the change introduced by @mizvekov in some tests. Maybe @zygoloid or @AaronBallman has some more input here.

Do you have a pointer to such changes?

@shafik
Copy link
Collaborator

shafik commented Sep 6, 2023

So it looks like some of these changes undo some of the change introduced by @mizvekov in some tests. Maybe @zygoloid or @AaronBallman has some more input here.

Do you have a pointer to such changes?

One of the commits is here: 15f3cd6

I know he did a lot of work in this area and I am not familiar with it in detail but I want to make sure interested parties are not stepping on each others work.

@jrtc27
Copy link
Collaborator Author

jrtc27 commented Sep 6, 2023

So it looks like some of these changes undo some of the change introduced by @mizvekov in some tests. Maybe @zygoloid or @AaronBallman has some more input here.

Do you have a pointer to such changes?

One of the commits is here: 15f3cd6

I know he did a lot of work in this area and I am not familiar with it in detail but I want to make sure interested parties are not stepping on each others work.

My view is that the 'struct S':'struct S' is just an unintended side-effect of adding that sugar. I'm not removing that sugar, and in cases where the as-written type differs from the desugared type it will still print both, it just doesn't print both when textually there is no difference.

Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good and like a nice improvement to me. I don't think this is undoing any of the intended functional changes of @mizvekov's work.

@mizvekov
Copy link
Contributor

mizvekov commented Sep 8, 2023

Yep, I definitely agree this is a good change, thanks for working on it!
I thought about doing the same at the time, but I just didn't have the bandwidth for yet another patch with a lot of test churn :)

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes generally LGTM, but please add a release note

Comment on lines +323 to +327
if (DSQT != SQT) {
std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
if (DSQTS != SQTS)
Ret["desugaredQualType"] = DSQTS;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aim with the original code was "if the desugared type and the given qual type are the same thing, only print one if we've been asked to print desugared", and this keeps that same aim, so I think this is reasonable.

That said, I agree with @cor3ntin that this needs a release note because there is a change in behavior that may break downstream consumers who expect the desugaredQualType field that's no longer going to show up for them. I don't expect it to be significantly disruptive in practice, but we should explicitly communicate that sort of change to users.

Comment on lines 684 to 685
// If the type is sugared, also dump a (shallow) desugared type when
// visibly different.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either approach is grammatically correct, this seems likely to be more about readability for ESL folks. I'm slightly in favor of the change, but don't have a strong opinion (If @cor3ntin thinks it helps readability for him, I think we should make the change -- he's French)

@@ -1351,7 +1351,6 @@ void testParmVarDecl(int TestParmVarDecl);
// CHECK-NEXT: "isUsed": true,
// CHECK-NEXT: "name": "x",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "desugaredQualType": "enum Enum",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this is an example of why we need the release note; the information didn't change, it flat-out disappeared which could catch some folks by surprise.

@jrtc27
Copy link
Collaborator Author

jrtc27 commented Sep 8, 2023

I've added a release note (with hopefully valid reST syntax) and made the source comment less terse as requested

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@@ -49,6 +49,28 @@ ABI Changes in This Version
- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer
be split between a register and a stack slot.

AST Dumping Potentially Breaking Changes
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic release note!!

@jrtc27 jrtc27 requested a review from cor3ntin September 9, 2023 19:10
Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

", where the aka will be skipped" in the commit message still doesn't make sense to me , otherwise lgtm

@jrtc27
Copy link
Collaborator Author

jrtc27 commented Sep 9, 2023

", where the aka will be skipped" in the commit message still doesn't make sense to me , otherwise lgtm

Comments in Clang's ASTDiagnostic use "aka" and "aka clause" synonymously, referring to the parenthesised clause in 'foo' (aka 'bar') that is sometimes printed in diagnostics. That clause is never printed if foo and bar are the same string, even if foo is sugared.

@jrtc27
Copy link
Collaborator Author

jrtc27 commented Oct 25, 2023

Rebased to verify CI still passes before merging (thanks Aaron for the reverse ping)

@jrtc27 jrtc27 force-pushed the ast-skip-desugar-identical branch from 3796dfc to f2526f9 Compare October 25, 2023 18:27
@llvmbot llvmbot added clang Clang issues not falling into any other category HLSL HLSL Language Support clang:openmp OpenMP related changes to Clang labels Oct 25, 2023
@github-actions
Copy link

github-actions bot commented Oct 25, 2023

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff a3e5c947c48ee2351ca47558767b397df9a3c598 e7a8e0804506266afa44a51ddb5a118d9df4db37 -- clang/lib/AST/JSONNodeDumper.cpp clang/lib/AST/TextNodeDumper.cpp clang/test/AST/ast-dump-APValue-anon-union.cpp clang/test/AST/ast-dump-APValue-struct.cpp clang/test/AST/ast-dump-APValue-union.cpp clang/test/AST/ast-dump-attr.cpp clang/test/AST/ast-dump-decl-json.c clang/test/AST/ast-dump-decl.cpp clang/test/AST/ast-dump-expr-json.c clang/test/AST/ast-dump-expr-json.cpp clang/test/AST/ast-dump-expr.c clang/test/AST/ast-dump-expr.cpp clang/test/AST/ast-dump-fpfeatures.cpp clang/test/AST/ast-dump-funcs.cpp clang/test/AST/ast-dump-functionprototype.cpp clang/test/AST/ast-dump-lambda.cpp clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp clang/test/AST/ast-dump-overloaded-operators.cpp clang/test/AST/ast-dump-records-json.cpp clang/test/AST/ast-dump-records.cpp clang/test/AST/ast-dump-recovery.cpp clang/test/AST/ast-dump-stmt-json.cpp clang/test/AST/ast-dump-stmt.cpp clang/test/AST/ast-dump-template-decls-json.cpp clang/test/AST/ast-dump-template-decls.cpp clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp clang/test/AST/ast-dump-temporaries-json.cpp clang/test/AST/ast-dump-types-json.cpp clang/test/AST/coroutine-locals-cleanup.cpp clang/test/AST/float16.cpp clang/test/AST/nrvo.c clang/test/AST/sourceranges.cpp clang/test/C/drs/dr253.c clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp clang/test/OpenMP/align_clause_ast_print.cpp clang/test/OpenMP/generic_loop_ast_print.cpp clang/test/OpenMP/scope_ast_print.cpp clang/test/SemaCXX/co_await-ast.cpp clang/test/SemaCXX/consteval-cleanup.cpp clang/test/SemaTemplate/aggregate-deduction-candidate.cpp clang/test/SemaTemplate/deduction-guide.cpp clang/test/SemaTemplate/default-expr-arguments-3.cpp clang/test/SemaTemplate/make_integer_seq.cpp clang/test/SemaTemplate/pr47676.cpp clang/test/SemaTemplate/type_pack_element.cpp clang/unittests/AST/ASTImporterTest.cpp
View the diff from clang-format here.
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 87e6cd1e1..7be53d444 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -4947,7 +4947,7 @@ TEST_P(ASTImporterOptionSpecificTestBase,
   `-CXXDeductionGuideDecl 0x1fe59c0 <col:36> col:36 implicit <deduction guide for A> 'auto (A<T>) -> A<T>'
     `-ParmVarDecl 0x1fe5958 <col:36> col:36 'A<T>'
 */
-// clang-format on
+  // clang-format on
   auto *FromD1 = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
       FromTU, cxxDeductionGuideDecl());
   auto *FromD2 = LastDeclMatcher<CXXDeductionGuideDecl>().match(

@llvmbot
Copy link
Member

llvmbot commented Oct 25, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-hlsl

Author: Jessica Clarke (jrtc27)

Changes

These are an artifact of how types are structured but serve little
purpose, merely showing that the type is sugared in some way. For
example, ElaboratedType's existence means struct S gets printed as
'struct S':'struct S' in the AST, which is unnecessary visual clutter.
Note that skipping the second print when the types have the same string
matches what we do for diagnostics, where the aka will be skipped.


Patch is 161.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/65214.diff

60 Files Affected:

  • (modified) clang/docs/HowToSetupToolingForLLVM.rst (+1-1)
  • (modified) clang/docs/ReleaseNotes.rst (+22)
  • (modified) clang/lib/AST/JSONNodeDumper.cpp (+7-3)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+9-4)
  • (modified) clang/test/AST/HLSL/this-reference-template.hlsl (+4-4)
  • (modified) clang/test/AST/ast-dump-APValue-anon-union.cpp (+5-5)
  • (modified) clang/test/AST/ast-dump-APValue-struct.cpp (+6-6)
  • (modified) clang/test/AST/ast-dump-APValue-union.cpp (+5-5)
  • (modified) clang/test/AST/ast-dump-attr.cpp (+6-6)
  • (modified) clang/test/AST/ast-dump-decl-json.c (-4)
  • (modified) clang/test/AST/ast-dump-decl-json.m (-1)
  • (modified) clang/test/AST/ast-dump-decl.cpp (+13-13)
  • (modified) clang/test/AST/ast-dump-decl.m (+1-1)
  • (modified) clang/test/AST/ast-dump-expr-json.c (-6)
  • (modified) clang/test/AST/ast-dump-expr-json.cpp (-40)
  • (modified) clang/test/AST/ast-dump-expr-json.m (-24)
  • (modified) clang/test/AST/ast-dump-expr.c (+3-3)
  • (modified) clang/test/AST/ast-dump-expr.cpp (+11-11)
  • (modified) clang/test/AST/ast-dump-fpfeatures.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-funcs.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-functionprototype.cpp (+3-3)
  • (modified) clang/test/AST/ast-dump-lambda.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-objc-arc-json.m (-1)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp (+22-22)
  • (modified) clang/test/AST/ast-dump-overloaded-operators.cpp (+8-8)
  • (modified) clang/test/AST/ast-dump-records-json.cpp (-7)
  • (modified) clang/test/AST/ast-dump-records.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-recovery.cpp (+6-6)
  • (modified) clang/test/AST/ast-dump-stmt-json.cpp (-60)
  • (modified) clang/test/AST/ast-dump-stmt.cpp (+26-26)
  • (modified) clang/test/AST/ast-dump-stmt.m (+1-1)
  • (modified) clang/test/AST/ast-dump-template-decls-json.cpp (-1)
  • (modified) clang/test/AST/ast-dump-template-decls.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (-2)
  • (modified) clang/test/AST/ast-dump-temporaries-json.cpp (-5)
  • (modified) clang/test/AST/ast-dump-types-json.cpp (-1)
  • (modified) clang/test/AST/coroutine-locals-cleanup.cpp (+2-2)
  • (modified) clang/test/AST/float16.cpp (+16-16)
  • (modified) clang/test/AST/nrvo.c (+6-6)
  • (modified) clang/test/AST/sourceranges.cpp (+2-2)
  • (modified) clang/test/C/drs/dr253.c (+1-1)
  • (modified) clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp (+3-3)
  • (modified) clang/test/Import/objc-param-decl/test.m (+1-1)
  • (modified) clang/test/OpenMP/align_clause_ast_print.cpp (+1-1)
  • (modified) clang/test/OpenMP/generic_loop_ast_print.cpp (+3-3)
  • (modified) clang/test/OpenMP/scope_ast_print.cpp (+2-2)
  • (modified) clang/test/SemaCXX/co_await-ast.cpp (+7-7)
  • (modified) clang/test/SemaCXX/consteval-cleanup.cpp (+7-7)
  • (modified) clang/test/SemaOpenCLCXX/address-space-deduction.clcpp (+1-1)
  • (modified) clang/test/SemaOpenCLCXX/addrspace-auto.clcpp (+4-4)
  • (modified) clang/test/SemaTemplate/aggregate-deduction-candidate.cpp (+17-17)
  • (modified) clang/test/SemaTemplate/deduction-guide.cpp (+6-6)
  • (modified) clang/test/SemaTemplate/default-expr-arguments-3.cpp (+3-3)
  • (modified) clang/test/SemaTemplate/make_integer_seq.cpp (+4-4)
  • (modified) clang/test/SemaTemplate/pr47676.cpp (+1-1)
  • (modified) clang/test/SemaTemplate/type_pack_element.cpp (+1-1)
  • (modified) clang/unittests/AST/ASTImporterTest.cpp (+1-1)
diff --git a/clang/docs/HowToSetupToolingForLLVM.rst b/clang/docs/HowToSetupToolingForLLVM.rst
index 62189511aeb2a2b..dc1c17b0ae68d6c 100644
--- a/clang/docs/HowToSetupToolingForLLVM.rst
+++ b/clang/docs/HowToSetupToolingForLLVM.rst
@@ -172,7 +172,7 @@ Examples:
   clang::ASTConsumer *newASTConsumer() (CompoundStmt 0x44da290 </home/alexfh/local/llvm/tools/clang/tools/clang-check/ClangCheck.cpp:64:40, line:72:3>
     (IfStmt 0x44d97c8 <line:65:5, line:66:45>
       <<<NULL>>>
-        (ImplicitCastExpr 0x44d96d0 <line:65:9> '_Bool':'_Bool' <UserDefinedConversion>
+        (ImplicitCastExpr 0x44d96d0 <line:65:9> '_Bool' <UserDefinedConversion>
   ...
   $ clang-check tools/clang/tools/clang-check/ClangCheck.cpp -ast-print -ast-dump-filter ActionFactory::newASTConsumer
   Processing: tools/clang/tools/clang-check/ClangCheck.cpp.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 42f20b9a9bb0410..4b53a4816e931f7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -113,6 +113,28 @@ ABI Changes in This Version
 - Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer
   be split between a register and a stack slot.
 
+AST Dumping Potentially Breaking Changes
+----------------------------------------
+- When dumping a sugared type, Clang will no longer print the desugared type if
+  its textual representation is the same as the sugared one. This applies to
+  both text dumps of the form ``'foo':'foo'`` which will now be dumped as just
+  ``'foo'``, and JSON dumps of the form:
+
+  .. code-block:: json
+
+    "type": {
+      "qualType": "foo",
+      "desugaredQualType": "foo"
+    }
+
+  which will now be dumped as just:
+
+  .. code-block:: json
+
+    "type": {
+      "qualType": "foo"
+    }
+
 What's New in Clang |release|?
 ==============================
 Some of the major new features and improvements to Clang are listed
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index beb07015f0bcbb4..25b94ec5616b19c 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -315,12 +315,16 @@ std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {
 
 llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {
   SplitQualType SQT = QT.split();
-  llvm::json::Object Ret{{"qualType", QualType::getAsString(SQT, PrintPolicy)}};
+  std::string SQTS = QualType::getAsString(SQT, PrintPolicy);
+  llvm::json::Object Ret{{"qualType", SQTS}};
 
   if (Desugar && !QT.isNull()) {
     SplitQualType DSQT = QT.getSplitDesugaredType();
-    if (DSQT != SQT)
-      Ret["desugaredQualType"] = QualType::getAsString(DSQT, PrintPolicy);
+    if (DSQT != SQT) {
+      std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
+      if (DSQTS != SQTS)
+        Ret["desugaredQualType"] = DSQTS;
+    }
     if (const auto *TT = QT->getAs<TypedefType>())
       Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl());
   }
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 15eb6c6191edf27..ca609cf2d2060c1 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -692,13 +692,18 @@ void TextNodeDumper::dumpBareType(QualType T, bool Desugar) {
   ColorScope Color(OS, ShowColors, TypeColor);
 
   SplitQualType T_split = T.split();
-  OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
+  std::string T_str = QualType::getAsString(T_split, PrintPolicy);
+  OS << "'" << T_str << "'";
 
   if (Desugar && !T.isNull()) {
-    // If the type is sugared, also dump a (shallow) desugared type.
+    // If the type is sugared, also dump a (shallow) desugared type when
+    // it is visibly different.
     SplitQualType D_split = T.getSplitDesugaredType();
-    if (T_split != D_split)
-      OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
+    if (T_split != D_split) {
+      std::string D_str = QualType::getAsString(D_split, PrintPolicy);
+      if (T_str != D_str)
+        OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
+    }
   }
 }
 
diff --git a/clang/test/AST/HLSL/this-reference-template.hlsl b/clang/test/AST/HLSL/this-reference-template.hlsl
index 3b7fba3efdc747e..60e057986ebf80f 100644
--- a/clang/test/AST/HLSL/this-reference-template.hlsl
+++ b/clang/test/AST/HLSL/this-reference-template.hlsl
@@ -35,12 +35,12 @@ void main() {
 // CHECK:     -CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <line:8:3, line:10:3> line:8:5 used getFirst 'int ()' implicit_instantiation implicit-inline
 // CHECK-NEXT:-CompoundStmt 0x{{[0-9A-Fa-f]+}} <col:16, line:10:3>
 // CHECK-NEXT:-ReturnStmt 0x{{[0-9A-Fa-f]+}} <line:9:4, col:16>
-// CHECK-NEXT:-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:11, col:16> 'int':'int' <LValueToRValue>
-// CHECK-NEXT:-MemberExpr 0x{{[0-9A-Fa-f]+}} <col:11, col:16> 'int':'int' lvalue .First 0x{{[0-9A-Fa-f]+}}
+// CHECK-NEXT:-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:11, col:16> 'int' <LValueToRValue>
+// CHECK-NEXT:-MemberExpr 0x{{[0-9A-Fa-f]+}} <col:11, col:16> 'int' lvalue .First 0x{{[0-9A-Fa-f]+}}
 // CHECK-NEXT:-CXXThisExpr 0x{{[0-9A-Fa-f]+}} <col:11> 'Pair<int, float>' lvalue this
 // CHECK-NEXT:-CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <line:12:3, line:14:3> line:12:5 used getSecond 'float ()' implicit_instantiation implicit-inline
 // CHECK-NEXT:-CompoundStmt 0x{{[0-9A-Fa-f]+}} <col:17, line:14:3>
 // CHECK-NEXT:-ReturnStmt 0x{{[0-9A-Fa-f]+}} <line:13:5, col:12>
-// CHECK-NEXT:-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:12> 'float':'float' <LValueToRValue>
-// CHECK-NEXT:-MemberExpr 0x{{[0-9A-Fa-f]+}} <col:12> 'float':'float' lvalue .Second 0x{{[0-9A-Fa-f]+}}
+// CHECK-NEXT:-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:12> 'float' <LValueToRValue>
+// CHECK-NEXT:-MemberExpr 0x{{[0-9A-Fa-f]+}} <col:12> 'float' lvalue .Second 0x{{[0-9A-Fa-f]+}}
 // CHECK-NEXT:-CXXThisExpr 0x{{[0-9A-Fa-f]+}} <col:12> 'Pair<int, float>' lvalue implicit this
diff --git a/clang/test/AST/ast-dump-APValue-anon-union.cpp b/clang/test/AST/ast-dump-APValue-anon-union.cpp
index 906bfe4857ed031..0e6466ee1fd7361 100644
--- a/clang/test/AST/ast-dump-APValue-anon-union.cpp
+++ b/clang/test/AST/ast-dump-APValue-anon-union.cpp
@@ -30,23 +30,23 @@ union U1 {
 
 void Test() {
   constexpr S0 s0{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s0 'const S0':'const S0' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s0 'const S0' constexpr listinit
   // CHECK-NEXT:  |   |-value: Struct
   // CHECK-NEXT:  |   | `-field: Union .i Int 42
 
   constexpr U0 u0a{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0a 'const U0':'const U0' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0a 'const U0' constexpr listinit
   // CHECK-NEXT:  |   |-value: Union None
 
   constexpr U0 u0b{3.1415f};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0b 'const U0':'const U0' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0b 'const U0' constexpr listinit
   // CHECK-NEXT:  |   |-value: Union .U0::(anonymous union at {{.*}}) Union .f Float 3.141500e+00
 
   constexpr U1 u1a{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1a 'const U1':'const U1' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1a 'const U1' constexpr listinit
   // CHECK-NEXT:  |   |-value: Union .U1::(anonymous union at {{.*}}) Union .f Float 0.000000e+00
 
   constexpr U1 u1b{3.1415f};
-  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1b 'const U1':'const U1' constexpr listinit
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1b 'const U1' constexpr listinit
   // CHECK-NEXT:      |-value: Union .U1::(anonymous union at {{.*}}) Union .f Float 3.141500e+00
 }
diff --git a/clang/test/AST/ast-dump-APValue-struct.cpp b/clang/test/AST/ast-dump-APValue-struct.cpp
index 04d1877c293d1a6..4730404abc287c6 100644
--- a/clang/test/AST/ast-dump-APValue-struct.cpp
+++ b/clang/test/AST/ast-dump-APValue-struct.cpp
@@ -60,12 +60,12 @@ struct S5 : S4 {
 
 void Test() {
   constexpr S0 s0{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s0 'const S0':'const S0' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s0 'const S0' constexpr listinit
   // CHECK-NEXT:  |   |-value: Struct
   // CHECK-NEXT:  |   | `-fields: Int 0, Union .j Int 0
 
   constexpr S1 s1{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s1 'const S1':'const S1' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s1 'const S1' constexpr listinit
   // CHECK-NEXT:  |   |-value: Struct
   // CHECK-NEXT:  |   | |-field: Int 0
   // CHECK-NEXT:  |   | `-field: Union .s
@@ -73,12 +73,12 @@ void Test() {
   // CHECK-NEXT:  |   |     `-field: Int 0
 
   constexpr S2 s2{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s2 'const S2':'const S2' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s2 'const S2' constexpr listinit
   // CHECK-NEXT:  |   |-value: Struct
   // CHECK-NEXT:  |   | `-fields: Int 0, Union .u Union .j Int 0
 
   constexpr S3 s3{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s3 'const S3':'const S3' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s3 'const S3' constexpr listinit
   // CHECK-NEXT:  |   |-value: Struct
   // CHECK-NEXT:  |   | |-field: Int 0
   // CHECK-NEXT:  |   | `-field: Union .u
@@ -87,7 +87,7 @@ void Test() {
   // CHECK-NEXT:  |   |       `-field: Int 0
 
   constexpr S4 s4{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s4 'const S4':'const S4' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s4 'const S4' constexpr listinit
   // CHECK-NEXT:  |   |-value: Struct
   // CHECK-NEXT:  |   | |-base: Struct
   // CHECK-NEXT:  |   | | `-fields: Int 0, Union .j Int 0
@@ -96,7 +96,7 @@ void Test() {
   // CHECK-NEXT:  |   | `-fields: Int 4, Int 5, Int 6
 
   constexpr S5 s5{};
-  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s5 'const S5':'const S5' constexpr listinit
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s5 'const S5' constexpr listinit
   // CHECK-NEXT:      |-value: Struct
   // CHECK-NEXT:      | |-base: Struct
   // CHECK-NEXT:      | | |-base: Struct
diff --git a/clang/test/AST/ast-dump-APValue-union.cpp b/clang/test/AST/ast-dump-APValue-union.cpp
index b70b5ea484a6e97..c717b6ece738276 100644
--- a/clang/test/AST/ast-dump-APValue-union.cpp
+++ b/clang/test/AST/ast-dump-APValue-union.cpp
@@ -39,25 +39,25 @@ union U3 {
 
 void Test() {
   constexpr U0 u0{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0 'const U0':'const U0' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0 'const U0' constexpr listinit
   // CHECK-NEXT:  |   |-value: Union .i Int 42
 
   constexpr U1 u1{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1 'const U1':'const U1' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1 'const U1' constexpr listinit
   // CHECK-NEXT:  |   |-value: Union .uinner Union .f Float 3.141500e+00
 
   constexpr U2 u2{};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u2 'const U2':'const U2' constexpr listinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u2 'const U2' constexpr listinit
   // CHECK-NEXT:  |   |-value: Union .uinner
   // CHECK-NEXT:  |   | `-Union .arr
   // CHECK-NEXT:  |   |   `-Array size=2
   // CHECK-NEXT:  |   |     `-elements: Int 1, Int 2
 
   constexpr U3 u3a = {.f = 3.1415};
-  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u3a 'const U3':'const U3' constexpr cinit
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u3a 'const U3' constexpr cinit
   // CHECK-NEXT:  |   |-value: Union .f Float 3.141500e+00
 
   constexpr U3 u3b = {.uinner = {}};
-  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u3b 'const U3':'const U3' constexpr cinit
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u3b 'const U3' constexpr cinit
   // CHECK-NEXT:      |-value: Union .uinner Union .d Float 3.141500e+00
 }
diff --git a/clang/test/AST/ast-dump-attr.cpp b/clang/test/AST/ast-dump-attr.cpp
index 8fd4a8f3a54c6c6..f5a748157142188 100644
--- a/clang/test/AST/ast-dump-attr.cpp
+++ b/clang/test/AST/ast-dump-attr.cpp
@@ -146,17 +146,17 @@ struct C { char a[16]; };
 // CHECK: ClassTemplateSpecializationDecl {{.*}} struct my_union
 // CHECK: CXXRecordDecl {{.*}} implicit struct my_union
 // CHECK: FieldDecl {{.*}} buffer 'char[1024]'
-// CHECK-NEXT: AlignedAttr {{.*}} alignas 'TestAligns::A':'TestAligns::A'
-// CHECK-NEXT: AlignedAttr {{.*}} alignas 'TestAligns::B':'TestAligns::B'
-// CHECK-NEXT: AlignedAttr {{.*}} alignas 'TestAligns::C':'TestAligns::C'
+// CHECK-NEXT: AlignedAttr {{.*}} alignas 'TestAligns::A'
+// CHECK-NEXT: AlignedAttr {{.*}} alignas 'TestAligns::B'
+// CHECK-NEXT: AlignedAttr {{.*}} alignas 'TestAligns::C'
 my_union<A, B, C> my_union_val;
 
 // CHECK: ClassTemplateSpecializationDecl {{.*}} struct my_union2
 // CHECK: CXXRecordDecl {{.*}} implicit struct my_union2
 // CHECK: FieldDecl {{.*}} buffer 'char[1024]'
-// CHECK-NEXT: AlignedAttr {{.*}} _Alignas 'TestAligns::A':'TestAligns::A'
-// CHECK-NEXT: AlignedAttr {{.*}} _Alignas 'TestAligns::B':'TestAligns::B'
-// CHECK-NEXT: AlignedAttr {{.*}} _Alignas 'TestAligns::C':'TestAligns::C'
+// CHECK-NEXT: AlignedAttr {{.*}} _Alignas 'TestAligns::A'
+// CHECK-NEXT: AlignedAttr {{.*}} _Alignas 'TestAligns::B'
+// CHECK-NEXT: AlignedAttr {{.*}} _Alignas 'TestAligns::C'
 my_union2<A, B, C> my_union2_val;
 
 } // namespace TestAligns
diff --git a/clang/test/AST/ast-dump-decl-json.c b/clang/test/AST/ast-dump-decl-json.c
index 55b918afaab5d2d..7f53cda5020b503 100644
--- a/clang/test/AST/ast-dump-decl-json.c
+++ b/clang/test/AST/ast-dump-decl-json.c
@@ -1351,7 +1351,6 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:    "isUsed": true,
 // CHECK-NEXT:    "name": "x",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "desugaredQualType": "enum Enum",
 // CHECK-NEXT:     "qualType": "enum Enum"
 // CHECK-NEXT:    }
 // CHECK-NEXT:   },
@@ -1424,7 +1423,6 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:           }
 // CHECK-NEXT:          },
 // CHECK-NEXT:          "type": {
-// CHECK-NEXT:           "desugaredQualType": "enum Enum",
 // CHECK-NEXT:           "qualType": "enum Enum"
 // CHECK-NEXT:          },
 // CHECK-NEXT:          "valueCategory": "prvalue",
@@ -1446,7 +1444,6 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:             }
 // CHECK-NEXT:            },
 // CHECK-NEXT:            "type": {
-// CHECK-NEXT:             "desugaredQualType": "enum Enum",
 // CHECK-NEXT:             "qualType": "enum Enum"
 // CHECK-NEXT:            },
 // CHECK-NEXT:            "valueCategory": "lvalue",
@@ -1455,7 +1452,6 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:             "kind": "ParmVarDecl",
 // CHECK-NEXT:             "name": "x",
 // CHECK-NEXT:             "type": {
-// CHECK-NEXT:              "desugaredQualType": "enum Enum",
 // CHECK-NEXT:              "qualType": "enum Enum"
 // CHECK-NEXT:             }
 // CHECK-NEXT:            }
diff --git a/clang/test/AST/ast-dump-decl-json.m b/clang/test/AST/ast-dump-decl-json.m
index 9d82c6696cb524f..f7067ac0d3b7701 100644
--- a/clang/test/AST/ast-dump-decl-json.m
+++ b/clang/test/AST/ast-dump-decl-json.m
@@ -911,7 +911,6 @@ void f(void) {
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "name": "T",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "desugaredQualType": "id",
 // CHECK-NEXT:     "qualType": "id",
 // CHECK-NEXT:     "typeAliasDeclId": "0x{{.*}}"
 // CHECK-NEXT:    }
diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp
index 017e640aeaea6d7..d74aa9045532e75 100644
--- a/clang/test/AST/ast-dump-decl.cpp
+++ b/clang/test/AST/ast-dump-decl.cpp
@@ -248,19 +248,19 @@ namespace testFunctionTemplateDecl {
   // CHECK-NEXT:  | |-TemplateArgument type 'testFunctionTemplateDecl::A'
   // CHECK-NEXT:  | | `-RecordType 0{{.+}} 'testFunctionTemplateDecl::A'
   // CHECK-NEXT:  | |   `-CXXRecord 0x{{.+}} 'A'
-  // CHECK-NEXT:  | |-ParmVarDecl 0x{{.+}} <col:50> col:51 'testFunctionTemplateDecl::A':'testFunctionTemplateDecl::A'
+  // CHECK-NEXT:  | |-ParmVarDecl 0x{{.+}} <col:50> col:51 'testFunctionTemplateDecl::A'
   // CHECK-NEXT:  | `-CompoundStmt 0x{{.+}} <col:53, col:55>
   // CHECK-NEXT:  |-Function 0x{{.+}} 'TestFunctionTemplate' 'void (B)'
   // CHECK-NEXT:  |-FunctionDecl 0x{{.+}} <col:24, col:55> col:29 TestFunctionTemplate 'void (testFunctionTemplateDecl::C)'
   // CHECK-NEXT:  | |-TemplateArgument type 'testFunctionTemplateDecl::C'
   // CHECK-NEXT:  | | `-RecordType 0{{.+}} 'testFunctionTemplateDecl::C'
   // CHECK-NEXT:  | |   `-CXXRecord 0x{{.+}} 'C'
-  // CHECK-NEXT:  | `-ParmVarDecl 0x{{.+}} <col:50> col:51 'testFunctionTemplateDecl::C':'testFunctionTemplateDecl::C'
+  // CHECK-NEXT:  | `-ParmVarDecl 0x{{.+}} <col:50> col:51 'testFunctionTemplateDecl::C'
   // CHECK-NEXT:  `-FunctionDecl 0x{{.+}} <col:24, col:55> col:29 TestFunctionTemplate 'void (testFunctionTemplateDecl::D)'
   // CHECK-NEXT:    |-TemplateArgument type 'testFunctionTemplateDecl::D'
   // CHECK-NEXT:    | `-RecordType 0{{.+}} 'testFunctionTemplateDecl::D'
   // CHECK-NEXT:    |   `-CXXRecord 0x{{.+}} 'D'
-  // CHECK-NEXT:    |-ParmVarDecl 0x{{.+}} <col:50> col:51 'testFunctionTemplateDecl::D':'testFunctionTemplateDecl::D'
+  // CHECK-NEXT:    |-ParmVarDecl 0x{{.+}} <col:50> col:51 'testFunctionTemplateDecl::D'
   // CHECK-NEXT:    `-CompoundStmt 0x{{.+}} <col:53, col:55>
 
   // CHECK:       FunctionDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-32]]:3, col:41> col:19 TestFunctionTemplate 'void (B)'
@@ -500,7 +500,7 @@ namespace testCanonicalTemplate {
   // CHECK-NEXT:     |-TemplateArgument type 'testCanonicalTemplate::A'{{$}}
   // CHECK-NEXT:     | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A'{{$}}
   // CHECK-NEXT:     |   `-CXXRecord 0x{{.+}} 'A'{{$}}
-  // CHECK-NEXT:     `-ParmVarDecl 0x{{.*}} <col:50> col:51 'testCanonicalTemplate::A':'testCanonicalTemplate::A'{{$}}
+  // CHECK-NEXT:     `-ParmVarDecl 0x{{.*}} <col:50> col:51 'testCanonicalTemplate::A'{{$}}
 
   // CHECK:      FunctionTemplateDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-12]]:3, col:51> col:29 TestFunctionTemplate{{$}}
   // CHECK-NEXT:   |-TemplateTypeParmDecl 0x{{.+}} <col:12, col:21> col:21 referenced typename depth 0 index 0 T{{$}}
@@ -613,15 +613,15 @@ namespace testCanonicalTemplate {
   // CHECK:      VarTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-11]]:7, col:43> col:43 TestVarTemplate{{$}}
   // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:16, col:25> col:25 referenced typename depth 0 index 0 T{{$}}
   // CHECK-NEXT: |-VarDecl 0x{{.+}} <col:28, col:43> col:43 TestVarTemplate 'const T' static{{$}}
-  // CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-11]]:3, col:34> col:14 referenced TestVarTemplate 'const int':'const int' implicit_instantiation cinit{{$}}
+  // CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-11]]:3, col:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
   // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}}
   // CHECK-NEXT: | |-TemplateArgument type 'int'{{$}}
   // CHECK-NEXT: | | `-BuiltinType 0x{{.+}} 'int'{{$}}
-  // CHECK-NEXT: | `-InitListExpr 0x{{.+}} <col:32, col:34> 'int':'int'{{$}}
-  // CHECK-NEXT: `-VarTemplateSpecializationDecl 0x{{.+}} <line:[[@LINE-19]]:28, col:43> col:43 referenced TestVarTemplate 'const int':'const int' implicit_instantiation static{{$}}
+  // CHECK-NEXT: | `-InitListExpr 0x{{.+}} <col:32, col:34> 'int'{{$}}
+  // CHECK-NEXT: `-VarTemplateSpecializationDecl 0x{{.+}} <line:[[@LINE-19]]:28, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
   // CHECK-NEXT:   `-Templa...
[truncated]

These are an artifact of how types are structured but serve little
purpose, merely showing that the type is sugared in some way. For
example, ElaboratedType's existence means struct S gets printed as
'struct S':'struct S' in the AST, which is unnecessary visual clutter.
Note that skipping the second print when the types have the same string
matches what we do for diagnostics, where the aka will be skipped.
@jrtc27 jrtc27 force-pushed the ast-skip-desugar-identical branch from f2526f9 to e7a8e08 Compare October 26, 2023 00:30
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jrtc27 jrtc27 merged commit f9ead46 into llvm:main Oct 26, 2023
2 of 3 checks passed
@jrtc27 jrtc27 deleted the ast-skip-desugar-identical branch October 26, 2023 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants