The rules of the specifier decltype are here: https://en.cppreference.com/w/cpp/language/decltype
Your case falls into any expression (third item), because *p is not a id-Expression, neither a class membership access, and yes any expression.
If the argument is any other Expression of type T, and
a. if the value Category of Expression is xvalue, then decltype yields T&&;
b. if the value Category of Expression is lvalue, then decltype yields T&;
c. if the value Category of Expression is prvalue, then decltype yields T.
The value category of the expression *p (indirect expression) is defined as a lvalue:
The following Expressions are lvalue Expressions:
- …
*p, the built-in indirection Expression;
So the kind where decltype(*p) results comes from rule 3.b.: if the value Category of Expression is lvalue, then decltype yields T&, where T is the type of expression *p, which in that case is int. Replacing, we have int& as the resulting type.