Summary: What does the keyword volatile do when applied to a function declaration in C and in C++?  
Details:
I see that it's possible to compile a function that is marked as volatile.  However, I'm not sure what compiler optimization (if any) this prevents.  For instance I created the following test case:
volatile int foo() {
  return 1;
}
int main() {
  int total = 0;
  int i = 0;
  for(i = 0; i < 100; i++) {
    total += foo();
  }
  return total;
}
When I compile with clang -emit-llvm -S -O3 test.c (gcc would also work but the llvm IR is more readable in my opinion) I get:
target triple = "x86_64-unknown-linux-gnu"
define i32 @foo() #0 {
  ret i32 1
}
define i32 @main() #0 {
  ret i32 100
}
So obviously the compiler was able to optimize away the calls to function foo() so that main() returns a constant, even though foo() is marked as volatile.  So my question is whether volatile does anything at all when applied to a function declaration in terms of limiting compiler optimizations.
(Note my interest in this question is mostly curiosity to understand what volatile does rather than to solve any specific problem.)
(Also I have marked this question as both C and C++ not because I think they are the same language, but because I am interested to know if there are differences in what volatile does in this case in these two languages).
 
     
    