According to 6.3 [basic.def.odr] paragraph 2,
A variable or non-overloaded function whose name appears as a potentially-evaluated expression is used... A virtual member function is used if it is not pure.
However, that does not adequately address when a pure virtual function is used or not used. For example,
struct S { virtual void pure1() = 0; virtual void pure2() = 0; }; void f(S* p) { p->pure1(); p->S::pure2(); };
Both pure1 and pure2 satisfy the criterion that their name appears in a potentially-evaluated expression, but pure1 should not be considered “used” (which would require that it be defined); pure2 is “used” and must be defined.