static_assert(refable<void>);
As per [temp.names]/8, refable<void> is a concept-id:
A concept-id is a simple-template-id where the template-name is a concept-name. A concept-id is a prvalue of type bool, and does not name a template specialization. A concept-id evaluates to true if the concept's normalized constraint-expression is satisfied ([temp.constr.constr]) by the specified template arguments and false otherwise.
The concept's normalization is thus not dependent on the template arguments in a given concept-id that names the concept, but something that is performed independently; however the use of a concept-id may be the trigger for performing normalization of a concept, [temp.constr.normal]/2:
[Note 1: Normalization of constraint-expressions is performed when determining the associated constraints ([temp.constr.constr]) of a declaration and when evaluating the value of an id-expression that names a concept specialization ([expr.prim.id]). — end note]
Constraint normalization is covered by [temp.constr.normal]/1, where particularly /1.4 is governing the OP's example:
The normal form of an expression E is a constraint that is defined as
follows:
[...]
/1.4 The normal form of a concept-id C<A1, A2, ..., An> is the normal form of the constraint-expression of C, after substituting A1, A2, ..., An for C's respective template
parameters in the parameter mappings in each atomic constraint. If
any such substitution results in an invalid type or expression, the
program is ill-formed; no diagnostic is required.
[Example 1:
template<typename T> concept A = T::value || true;
template<typename U> concept B = A<U*>;
template<typename V> concept C = B<V&>;
Normalization of B's constraint-expression is valid and results in
T::value (with the mapping T↦U*) ∨ true (with an empty
mapping), despite the expression T::value being ill-formed for a
pointer type T. Normalization of C's constraint-expression results
in the program being ill-formed, because it would form the invalid
type V&* in the parameter mapping. — end example]
The key question here is whether OP's example runs into the
substituting [...] in the parameter mappings in each atomic constraint. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required.
or not.
The normalization of refable's constraint-expression, however, results in true (with an empty mapping), with emphasis on the empty mapping in this normalized constraint. Thus, the normal form of OP's refable<void> concept-id, would be substituting void into the parameter mapping of the normalized form of refable, but this only contains an empty parameter mapping. Thus the program is not ill-formed, NDR under [temp.constr.normal]/1.4, and the parameter mapping will never fail as there is nothing to substitute in the single empty mapping.
The question whether
refable<void>
results in a satisfied (true) constraint or not (false) comes down to how to interpret [temp.constr.atomic]/3:
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. If substitution results in an invalid type or expression, the constraint is not satisfied. [...]
This one is a bit tricky to read unambiguously (particularly the emphasized part), but as the parameter mapping is empty, there can be no substitution failure regarding the parameter mapping, and I interpret the emphasized part as substitution of template arguments into the normalized constraint-expression, which contains no template parameters, meaning there is no substitution failure. This would argue for GCC actually being correct to accept the program.