Search code examples
c++cgccincludeinclude-path

Protecting certain include locations


I'm building a little language that will compile to C or C++, I haven't decided yet, however I have come across a dilemma concerning the #include keyword.

My language will come with a standard library that will be incorporated into the language, and be accessible much like that of C or C++ with the standard includes such as #include <string>.

My compiler can automatically tell the difference between user includes and standard library includes, but my issue lies in how the GCC compiler uses the -I flag.

Let's take Java as an example. One of the default packages (folder) is called java.util. If I try to make my own folder called java.util inside my project, I get the error:

The package java.util conflicts with a package accessible from another module: java.base

Meaning it is included by default.

I would like this to do the same thing in C++, but am worried that a user could (hypothetically) do a relative path include and cause a conflict.

Take for example, I use the flag like so: -I ../some/folder.

However then the user could simply type #include "../some/folder" to access the same content. Is there any way I can restrict this, and like the title of the question suggests, "protect" the folder from being called like that?

Furthermore, if there is a file inside of that folder called test.h and the user decides to create their own file called test.h locally and include it. How will the conflicts occur? Will it pick the local folder over the included via. flags?

An example of a basic implementation is as follows: (General syntax, no specific language)

boolean userDefine = false;
string defineName = "foo";

// Do something to determine if <> define or "" define.

if (userDefine) {
    // Returns #include "foo"
    return "#include \"" + defineName + "\"";
} else {
    // Returns #include "stdlib/foo"
    return "#include \"stdlib/" + defineName + "\"";
}

But then again, the user could include the folder so that it satisfies the first condition and still gain access.


Solution

  • It's pretty much the standard practice to put any #include files at the very beginning of the C++ source file, as the first order of business.

    Of course, a #include can appear anywhere in the C++ source file, and there are situations when that happens but, if you were to grab some random C++ source from github, chances are pretty good that all the #include files will be at the beginning of the file.

    So, all you have to do, is to make arrangements that your library's #include is always at the beginning, and use the standard #ifndef/#define guards in your header files. Then, manual inclusion of them subsequently will have no effect whatsoever, no matter what path is used.

    Of course, this won't stop anyone from manually #undefing your guard, to create some chaos. However, C++ never had a reputation for reliably preventing you from shooting yourself in the foot, and is unlikely to earn that reputation in the foreseeable future; so what? Actually, most compilers implement #pragma once, which might be a slightly better foot self-shooting prevention approach...