query regarding system-header-simulator.h

Hello,
What is the purpose of this header file system-header-simulator.h at llvm_3.1_src\tools\clang\test\Analysis ?

Regards,
Jyoti

Hi, Jyoti. The static analyzer treats some functions differently if they come from a system header – for example, it is assumed that system functions do not arbitrarily free() their parameters, and that some bugs found in system headers cannot be fixed by the user and should be suppressed. system-header-simulator.h uses “#pragma clang system_header” so that this behavior can be tested without relying on the actual headers on your system.

Hope that answers your question!
Jordan

There ought to be a comment to that effect :slight_smile:

Csaba

Hi Jordan,
I understand it’s overall purpose now. However, need some more clarity. So does this mean that if system-header-simulator.h is included
in a test file all system function declarations in system headers will be overridden by those in system-header-simulator.h ?
In effect, i want to know what #pragma clang system_header" means or what it does?
I know #pragma clang is a directive to clang and it is informing something about system headers to clang but precisely what is my question.
Does it also mean that it should be possible to compile a test file invoking system functions by just including system-header-simulator.h
file and not including the system headers directly ?
I did try by including malloc in test file div-zero.cpp and including system-header-simulator.h instead of stdlib.h, but fails to compile.

Thanks in advance.

Hi Jordan,
I understand it’s overall purpose now. However, need some more clarity. So does this mean that if system-header-simulator.h is included
in a test file all system function declarations in system headers will be overridden by those in system-header-simulator.h ?
In effect, i want to know what #pragma clang system_header" means or what it does?
I know #pragma clang is a directive to clang and it is informing something about system headers to clang but precisely what is my question.
Does it also mean that it should be possible to compile a test file invoking system functions by just including system-header-simulator.h
file and not including the system headers directly ?
I did try by including malloc in test file div-zero.cpp and including system-header-simulator.h instead of stdlib.h, but fails to compile.

Thanks in advance.

Hi Jordan,
I understand it’s overall purpose now. However, need some more clarity. So does this mean that if system-header-simulator.h is included
in a test file all system function declarations in system headers will be overridden by those in system-header-simulator.h ?

No, no. The philosophy behind the Clang regression tests is that none of them should include system headers*, so that we don’t depend on the user’s build environment to run the test suite. #include-ing system-header-simulator.h is just like #include-ing any other header in that it doesn’t replace anything, but in this case we didn’t include any of the system headers anyway.

  • The one exception to this rule is the compiler-specific headers that are shipped alongside clang itself, which some people would consider to be “system headers” (and which have the same behavior changes as actual headers from your system).

In effect, i want to know what #pragma clang system_header" means or what it does?

I know #pragma clang is a directive to clang and it is informing something about system headers to clang but precisely what is my question.

Basically, it means “pretend this file came from /usr/include (or wherever MSVC stores the headers for Windows) so that we get the same behavior tweaks”. I can’t think of any real-world uses off the top of my head, but it’s very useful for testing.

Does it also mean that it should be possible to compile a test file invoking system functions by just including system-header-simulator.h
file and not including the system headers directly ?
I did try by including malloc in test file div-zero.cpp and including system-header-simulator.h instead of stdlib.h, but fails to compile.

In C (and C++, and Objective-C), headers just tell you what functions and types are present. If you declare them yourself (in a header file, in your main source file, or in a fake system header like system-header-simulator.h), you can write code that uses them, and it will “compile”. However, the real definitions of system functions live in the system DLLs (or in a statically-linked system library), and so if you get the names wrong in your declarations then your program will fail to link, and if you get the names right but the types wrong your program will crash at runtime.

This has nothing to do with system headers or not system headers; it’s just how C works.

If you’re still confused, replace the word “system” in the pragma with “lenient-but-sane”, which is a rough description of how we treat system headers. We don’t warn about things as much, because we know the user won’t want to modify this header (the “lenient” bit), but we also assume that the code is probably doing the right thing, because it’s production code that’s running every day and is presumably well-tested (the “sane” bit). (For example, in the analyzer specifically, we assume functions like fopen() will be sane and not free the C string you pass to it.) By default, we assume all headers that come from certain locations like /usr/include (“system headers”) are “sane” and we should be “lenient” about diagnosing issues within them.

Jordan

Hi Jordan,
I understand it’s overall purpose now. However, need some more clarity. So does this mean that if system-header-simulator.h is included
in a test file all system function declarations in system headers will be overridden by those in system-header-simulator.h ?

No, no. The philosophy behind the Clang regression tests is that none of them should include system headers*, so that we don’t depend on the user’s build environment to run the test suite. #include-ing system-header-simulator.h is just like #include-ing any other header in that it doesn’t replace anything, but in this case we didn’t include any of the system headers anyway.

  • The one exception to this rule is the compiler-specific headers that are shipped alongside clang itself, which some people would consider to be “system headers” (and which have the same behavior changes as actual headers from your system).

In effect, i want to know what #pragma clang system_header" means or what it does?

I know #pragma clang is a directive to clang and it is informing something about system headers to clang but precisely what is my question.

Basically, it means “pretend this file came from /usr/include (or wherever MSVC stores the headers for Windows) so that we get the same behavior tweaks”. I can’t think of any real-world uses off the top of my head, but it’s very useful for testing.

Does it also mean that it should be possible to compile a test file invoking system functions by just including system-header-simulator.h
file and not including the system headers directly ?
I did try by including malloc in test file div-zero.cpp and including system-header-simulator.h instead of stdlib.h, but fails to compile.

In C (and C++, and Objective-C), headers just tell you what functions and types are present. If you declare them yourself (in a header file, in your main source file, or in a fake system header like system-header-simulator.h), you can write code that uses them, and it will “compile”. However, the real definitions of system functions live in the system DLLs (or in a statically-linked system library), and so if you get the names wrong in your declarations then your program will fail to link, and if you get the names right but the types wrong your program will crash at runtime.

This has nothing to do with system headers or not system headers; it’s just how C works.

Ofcourse, extern-ing a system function declaration will compel the compilation. So, “system-header-simulator.h” is just another header file to place such extern declarations in a common place and there is nothing more to it than that.

If you’re still confused, replace the word “system” in the pragma with “lenient-but-sane”, which is a rough description of how we treat system headers. We don’t warn about things as much, because we know the user won’t want to modify this header (the “lenient” bit), but we also assume that the code is probably doing the right thing, because it’s production code that’s running every day and is presumably well-tested (the “sane” bit). (For example, in the analyzer specifically, we assume functions like fopen() will be sane and not free the C string you pass to it.) By default, we assume all headers that come from certain locations like /usr/include (“system headers”) are “sane” and we should be “lenient” about diagnosing issues within them.

Jordan

Thanks for the detailed explanation of philosophy of clang & analyzer regression test considerations.