It does three things, basically:
- It adds
#include <Arduino.h>
to the top of your file, which gives you access to all the classes, functions and defined variables/macros of the API. - It matches
#include
entries with libraries and adds the files in those libraries to the list of files to compile, and - It scans through the ino file(s) looking for functions and adds prototypes to them to the top of your file.
It's the latter that can cause problems. Historically it never got the prototypes in the right place, and if you ever passed a structure of your own devising to a function it would break horribly. It does a better job these days, but it's still not 100% perfect.
It basically means that you don't have to adhere to the "You must define it before you use it" rule of C/C++. Which of course makes for lazy programmers.