llvm-project/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp
Krystian Stasiowski 652ae4ecad
[Clang][Sema] Warn when 'exclude_from_explicit_instantiation' attribute is used on local classes and members thereof (#88777)
A local class and its members declared in a function template are
instantiated alongside the definition of that template. It therefore
does not make sense to apply the `exclude_from_explicit_instantiation`
attribute to such declarations, and this patch adds a warning to
diagnose these cases (in addition to ignoring the attribute).

(The motivation for this patch is to fix a failing test in libc++ for
#84050. In particular, line 199 in `include/__memory/uses_allocator_construction.h`
in libc++ contains the expression `this->__value_` (reduced to 
https://godbolt.org/z/KqEerKWPd) which will be looked up prior
to instantiation once #84050 lands (the lookup context is the 
current instantiation). `_LIBCPP_HIDE_FROM_ABI` includes 
`__attribute__((exclude_from_explicit_instantiation))`, which in the 
reduced example results in `Local` being instantiated with 
`Local::operator A` as its `DeclContext`)
2024-04-18 07:48:10 -04:00

65 lines
1.7 KiB
C++

// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
// Test that the exclude_from_explicit_instantiation attribute is ignored
// for local classes and members thereof.
#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) // expected-note 0+{{expanded from macro}}
namespace N0 {
template<typename T>
void f() {
struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION A { // expected-warning {{attribute ignored on local class}}
// expected-note@-1 2{{in instantiation of}}
EXCLUDE_FROM_EXPLICIT_INSTANTIATION void g(T t) { // expected-warning {{attribute ignored on local class member}}
*t; // expected-error {{indirection requires pointer operand ('int' invalid)}}
}
struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION B { // expected-warning {{attribute ignored on local class}}
void h(T t) {
*t; // expected-error {{indirection requires pointer operand ('int' invalid)}}
}
};
};
}
template void f<int>(); // expected-note 2{{in instantiation of}}
}
// This is a reduced example from libc++ which required that 'value'
// be prefixed with 'this->' because the definition of 'Local::operator A'
// was not instantiated when the definition of 'g' was.
namespace N1 {
struct A { };
struct B {
operator A() {
return A();
}
};
template<typename T>
auto f(T t) {
return A(t);
}
template<typename T>
auto g(T t) {
struct Local {
T value;
EXCLUDE_FROM_EXPLICIT_INSTANTIATION // expected-warning {{attribute ignored on local class member}}
operator A() {
return A(value);
}
};
return f(Local(t));
}
auto x = g(B());
}