In pgmspace.h, the pgm_read_xxx()-s' parameter (the address) is explicitly cast to (uint16_t) through a macro, such as in:
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
While the parameter is supposed to be a pointer, this enables to use any garbage (read: non-pointer expression used by error) quietly.
Opposed to this are the similar accessing functions in eeprom.h.
I may be missing some reason for the different approach, but I assume this is mostly for historical reasons and better to be fixed before the next release of avr-libc/WinAVR.