Files
llvm-project/clang/test/CodeGen/block-with-perdefinedexpr.cpp
Michael Buch 4ef6419164 [clang][TypePrinter] Unify printing of anonymous/unnamed tag types (#169445)
In https://github.com/llvm/llvm-project/pull/168534 we made the
`TypePrinter` re-use `printNestedNameSpecifier` for printing scopes.
However, the way that the names of anonymous/unnamed types get printed
by the two are slightly inconsistent with each other.

`printNestedNameSpecifier` calls all `TagType`s without an identifer
`(anonymous)`. On the other hand, `TypePrinter` prints them slightly
more accurate (it differentiates anonymous vs. unnamed decls) and allows
for some additional customization points. E.g., with `MSVCFormatting`,
it will print `` `unnamed struct'`` instead of `(unnamed struct)`.
`printNestedNameSpecifier` already accounts for `MSVCFormatting` for
namespaces, but doesn't for `TagType`s. This inconsistency means that if
an unnamed tag is printed as part of a scope then it's displayed as
`(anonymous struct)`, but if it's the entity whose scope is being
printed, then it shows as `(unnamed struct)`.

This patch moves the printing of anonymous/unnamed tags into
`TagDecl::printName`. All the callsites that previously printed
anonymous tag decls now call `printName` to handle it. To preserve the
behaviour of not printing the kind name (i.e., `struct`/`class`/`enum`)
when printing the inner type of an elaborated type (i.e., avoiding
`struct (unnamed struct)`), this patch adds a
`PrintingPolicy::SuppressTagKeywordInAnonNames` that is appropriately
set when we want to suppress the tag keyword inside the anonymous name.
I had to make sure we set this bit to `false` when printing
nested-name-specifiers because we always want the tag keyword there
(e.g., `foo::(anonymous struct)::bar`) and for a `clangd` special case
which is described in a comment in the source.

**Test changes**

Mostly we now more accurately print the kind name of anonymous entities.
So there's a lot of `anonymous` -> `unnamed` changes. There are a
handful of `clangd` tests where the name of the entity is now `(unnamed
struct)` instead of just `(unnamed)`. That should be consistent with how
we choose to omit the tag keyword elsewhere. Since we're just printing
the name of the entity here, we include the kind tag.
2026-01-06 10:57:59 +00:00

88 lines
3.9 KiB
C++

// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 -std=c++11 | FileCheck %s
void bar() {
// CHECK-DAG: @__FUNCTION__.___Z3barv_block_invoke = private unnamed_addr constant [17 x i8] c"bar_block_invoke\00", align 1
const char * (^block1)() = ^() {
return __FUNCTION__;
};
// CHECK-DAG: @__FUNCTION__.___Z3barv_block_invoke_2 = private unnamed_addr constant [19 x i8] c"bar_block_invoke_2\00", align 1
const char * (^block2)() = ^() {
return __FUNCTION__;
};
}
void baz() {
// CHECK-DAG: @__PRETTY_FUNCTION__.___Z3bazv_block_invoke = private unnamed_addr constant [24 x i8] c"void baz()_block_invoke\00", align 1
const char * (^block1)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__PRETTY_FUNCTION__.___Z3bazv_block_invoke_2 = private unnamed_addr constant [26 x i8] c"void baz()_block_invoke_2\00", align 1
const char * (^block2)() = ^() {
return __PRETTY_FUNCTION__;
};
}
namespace foonamespace {
class Foo {
public:
Foo() {
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3FooC2Ev_block_invoke = private unnamed_addr constant [38 x i8] c"foonamespace::Foo::Foo()_block_invoke\00", align 1
const char * (^block1)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3FooC2Ev_block_invoke_2 = private unnamed_addr constant [40 x i8] c"foonamespace::Foo::Foo()_block_invoke_2\00", align 1
const char * (^block2)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__func__.___ZN12foonamespace3FooC2Ev_block_invoke_3 = private unnamed_addr constant [19 x i8] c"Foo_block_invoke_3\00", align 1
const char * (^block3)() = ^() {
return __func__;
};
bar();
inside_lambda();
}
~Foo() {
// CHECK-DAG: @__func__.___ZN12foonamespace3FooD2Ev_block_invoke = private unnamed_addr constant [18 x i8] c"~Foo_block_invoke\00", align 1
const char * (^block1)() = ^() {
return __func__;
};
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3FooD2Ev_block_invoke_2 = private unnamed_addr constant [41 x i8] c"foonamespace::Foo::~Foo()_block_invoke_2\00", align 1
const char * (^block2)() = ^() {
return __PRETTY_FUNCTION__;
};
}
void bar() {
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3Foo3barEv_block_invoke = private unnamed_addr constant [43 x i8] c"void foonamespace::Foo::bar()_block_invoke\00", align 1
const char * (^block1)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3Foo3barEv_block_invoke_2 = private unnamed_addr constant [45 x i8] c"void foonamespace::Foo::bar()_block_invoke_2\00", align 1
const char * (^block2)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__func__.___ZN12foonamespace3Foo3barEv_block_invoke_3 = private unnamed_addr constant [19 x i8] c"bar_block_invoke_3\00", align 1
const char * (^block3)() = ^() {
return __func__;
};
}
void inside_lambda() {
auto lambda = []() {
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke = private unnamed_addr constant [83 x i8] c"auto foonamespace::Foo::inside_lambda()::(lambda)::operator()() const_block_invoke\00", align 1
const char * (^block1)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke_2 = private unnamed_addr constant [85 x i8] c"auto foonamespace::Foo::inside_lambda()::(lambda)::operator()() const_block_invoke_2\00", align 1
const char * (^block2)() = ^() {
return __PRETTY_FUNCTION__;
};
// CHECK-DAG: @__func__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke_3 = private unnamed_addr constant [26 x i8] c"operator()_block_invoke_3\00", align 1
const char * (^block3)() = ^() {
return __func__;
};
};
lambda();
}
};
Foo f;
}