Skip to content

Commit f24e5b8

Browse files
committed
[Clang][Diagnostics] Simplify 'decltype(T{})' to 'T' in diagnostics
Clang's type printer would verbosely print `decltype(T{})` in diagnostics, even though this is equivalent to just `T`. This made error messages unnecessarily long and harder to read. This commit modifies `TypePrinter::printDecltypeBefore` to detect this specific pattern. It checks if the underlying expression of a `DecltypeType` is a default `CXXConstructExpr` (i.e., `T{}`) and, if so, prints the constructor's type (`T`) directly instead of the full `decltype`. Fixes #96638.
1 parent 0367711 commit f24e5b8

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

clang/lib/AST/TypePrinter.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/AST/DeclObjC.h"
1919
#include "clang/AST/DeclTemplate.h"
2020
#include "clang/AST/Expr.h"
21+
#include "clang/AST/ExprCXX.h"
2122
#include "clang/AST/NestedNameSpecifier.h"
2223
#include "clang/AST/PrettyPrinter.h"
2324
#include "clang/AST/TemplateBase.h"
@@ -1321,6 +1322,18 @@ void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
13211322
void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
13221323

13231324
void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
1325+
// Check for the 'decltype(T{})' pattern and simplify it to 'T'.
1326+
if (const Expr *E = T->getUnderlyingExpr()) {
1327+
E = E->IgnoreParenImpCasts();
1328+
if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
1329+
// Check if it's a default constructor (T{}) and not a list init (T{...})
1330+
if (CE->getNumArgs() == 0 && !CE->isListInitialization()) {
1331+
CE->getType().print(OS, Policy);
1332+
spaceBeforePlaceHolder(OS);
1333+
return; // Skip the default 'decltype(...)' printing
1334+
}
1335+
}
1336+
}
13241337
OS << "decltype(";
13251338
if (const Expr *E = T->getUnderlyingExpr()) {
13261339
PrintingPolicy ExprPolicy = Policy;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// clang/test/SemaCXX/decltype-diagnostic-print.cpp
2+
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
3+
4+
template <typename T>
5+
struct TestAssert {
6+
// This static_assert will fail, forcing the compiler to print the name
7+
// of the template instantiation in its diagnostic "note".
8+
static_assert(sizeof(T) == 0, "Static assert to check type printing");
9+
};
10+
11+
struct MySimpleType {};
12+
struct MyOtherType {};
13+
14+
void test() {
15+
// This will fail the static_assert.
16+
TestAssert<decltype(MySimpleType{})> test1;
17+
// expected-error@6 {{Static assert to check type printing}}
18+
// expected-note@16 {{in instantiation of template class 'TestAssert<MySimpleType>' requested here}}
19+
// CHECK-NOT: decltype(MySimpleType{})
20+
21+
TestAssert<decltype(MyOtherType{})> test2;
22+
// expected-error@6 {{Static assert to check type printing}}
23+
// expected-note@22 {{in instantiation of template class 'TestAssert<MyOtherType>' requested here}}
24+
// CHECK-NOT: decltype(MyOtherType{})
25+
}

0 commit comments

Comments
 (0)