xref: /llvm-project/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp (revision 131b4620ee7847102479f399ce3e35a3c1cb5461)
1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
3 
4 // C++ [basic.def.odr]p2:
5 //   An expression is potentially evaluated unless it [...] is the
6 //   operand of the typeid operator and the expression does not
7 //   designate an lvalue of polymorphic class type.
8 
9 // FIXME: This should really include <typeinfo>, but we don't have that yet.
10 namespace std {
11   class type_info;
12 }
13 
14 struct Poly {
15   virtual ~Poly();
16 };
17 
18 struct NonPoly { };
19 
20 template<typename T, typename Result = T>
21 struct X {
fX22   Result f(T t) { return t + t; } // expected-error{{invalid operands}}
23 
gX24   void g(T t) {
25     (void)typeid(f(t)); // expected-note{{here}}
26   }
27 };
28 
test(X<Poly> xp,X<Poly,Poly &> xpr,X<NonPoly> xnp,X<NonPoly,NonPoly &> xnpr)29 void test(X<Poly> xp, X<Poly, Poly&> xpr, X<NonPoly> xnp, X<NonPoly, NonPoly&> xnpr) {
30   // These are okay (although GCC and EDG get them wrong).
31   xp.g(Poly());
32   xnp.g(NonPoly());
33   xnpr.g(NonPoly());
34 
35   // Triggers an error (as it should);
36   xpr.g(Poly()); // expected-note{{instantiation of member function}}
37 }
38 
39 #if __cplusplus >= 202002L
40 
41 namespace unevaluated {
42 
43 struct S {
44   void f();
45 };
46 struct T {
47   virtual void f();
48 };
49 
null_s()50 consteval S *null_s() { return nullptr; }
make_s()51 consteval S *make_s() { return new S; }
null_t()52 consteval T *null_t() { return nullptr; }
make_t()53 consteval T *make_t() { return new T; } // #alloc
54 
func()55 void func() {
56   (void)typeid(*null_s());
57   (void)typeid(*make_s());
58   (void)typeid(*null_t()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
59   (void)typeid(*make_t()); // expected-error {{call to consteval function 'unevaluated::make_t' is not a constant expression}} \
60                               expected-note {{pointer to heap-allocated object is not a constant expression}} \
61                               expected-note@#alloc {{heap allocation performed here}} \
62                               expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
63 }
64 
65 } // namespace unevaluated
66 
67 #endif
68