Last active
March 22, 2018 08:34
-
-
Save bstaletic/89b265f3eb9f1dde5988a812cb6669ec to your computer and use it in GitHub Desktop.
Flag sanitisation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <regex> // Consider boost::regex - it's much faster | |
static const std::vector<std::string> INCLUDE_FLAGS {"-isystem", | |
"-I", | |
"-iquote", | |
"-isysroot", | |
"--sysroot", | |
"-gcc-toolchain", | |
"-include-pch", | |
"-include", | |
"-iframework", | |
"-F", | |
"-imacros", | |
"-idirafter"} | |
static const std::vector<std::string> INCLUDE_FLAGS_WIN {"/I"} | |
static const std::vector<std::string> STATE_FLAGS {"-c", | |
"-MP", | |
"-MD", | |
"-MMD", | |
"--fcolor-diagnostics"}; | |
static const std::vector<std::string> FILE_FLAGS {"-MF", | |
"-MT", | |
"-MQ", | |
"-o", | |
"--serialize-diagnostics"}; | |
namespace LibClangSanitiser { | |
namespace { | |
void SkipUnusedFlags(std::vector<std::string>& flags, bool clang_cl) { | |
auto it = flags.begin(); | |
if (!flags[0][0] == '-') ++it; | |
while (it != flags.end()) { | |
for (auto state_flag : STATE_FLAGS) { | |
if (*it == state_flag) it = flags.erase(it); | |
continue; | |
} | |
for (auto file_flag : FILE_FLAGS) { | |
if (*it == file_flag) it = flags.erase(it, it+1); | |
continue; | |
} | |
//if (*it == TU) it = flags.erase(it); | |
if SkipStrayFilenameFlag(*it, *(it - 1), clang_cl) { | |
it = flags.erase(it); | |
continue; | |
} | |
++it; | |
} | |
} | |
bool SkipStrayFilenameFlag(current_flag, previous_flag, clang_cl) { | |
bool current_starts_with_dash = current_flag[0] == '-'; | |
bool current_starts_with_slash = current_flag[0] == '/'; | |
bool current_may_be_path = current_flag.find('/') != std::string::npos || | |
(current_flag.find('\\)' != std::string::npos && | |
clang_cl); | |
bool current_flag_looks_like_flag = current_starts_with_dash || | |
(current_starts_with_slash && clang_cl); | |
bool previous_starts_with_dash = previous_flag[0] == '-'; | |
bool previous_starts_with_slash = previous_flag[0] == '/'; | |
bool previous_is_include = false; | |
for (auto include_flag : INCLUDE_FLAGS) { | |
if (previous_flag == include_flag) { | |
previous_is_include = true; | |
break; | |
} | |
} | |
if (!previous_is_include) { | |
for (auto include_flag_win : INCLUDE_FLAGS_WIN) { | |
if (previous_flag == include_flag_win) { | |
previous_is_include = true; | |
break; | |
} | |
} | |
} | |
bool previous_flag_looks_like_flag = previous_starts_with_dash || | |
(previous_starts_with_slash && clang_cl); | |
return !current_flag_looks_like_flag || | |
!previous_flag_looks_like_flag || | |
(!previous_is_include && current_may_be_path); | |
} | |
void RemoveXclangFlags(std::vector<std::string>& flags) { | |
for (auto it = flags.begin(); it != flags.end();) { | |
if (*it == "-Xclang") { | |
it = flags.erase(it, it + 1); | |
} else { | |
++it; | |
} | |
} | |
} | |
void RemoveFlagsPreceedingCompiler(std::vector<std::string>& flags, clang_cl) { | |
for (auto it = flags.begin(); it != flags.end(); ++it) { | |
if (*it[0] == '-') break; | |
if (*it[0] == '/' && clang_cl) break; | |
} | |
flags.erase(flags.begin(), --it); | |
} | |
void AddLanguageFlagIfCppFound(std::vector<std::string>& flags, bool clang_cl) { | |
RemoveFlagsPreceedingCompiler(flags, clang_cl); | |
const std::regex regex("\\+\\+(-\\d+('.'d+){0,2})?$", std::regex::optimize); | |
if (std::regex_search(flags[0], regex)) { | |
flags.insert(flags.begin() + 1, "-xc++"); | |
} | |
} | |
bool EnableClangClFlags(const std::vector<std::string>& flags) { | |
#ifdef _WIN32 | |
for (auto it = flags.rbegin(); it != flags.rend(); ++it) { | |
if (it->find("--driver-mode=") == 0) { | |
return *it == "--driver-mode=cl"; | |
} | |
} | |
std::string compiler_flag = flags[0]; | |
std::transform(compiler_flag.begin(), | |
compiler_flag.end(), | |
compiler_flag.begin(), | |
::tolower); | |
return compiler_flag.find("clang-cl") != std::string::npos || | |
compiler_flag.find("cl.exe") != std::string::npos; | |
#endif | |
return false; | |
} | |
void EnableTypoCorrection(std::vector<std::string>& flags) { | |
if (!flags.find("-fno-spell-checking")) { | |
flags.emplace_back("-fspell-checking"); | |
} | |
} | |
} // unnamed namespace | |
std::string PrepareFlagsForLibClang(std::vector<std::string> flags) { | |
bool clang_cl = EnableClangClFlags(flags); | |
AddLanguageFlagIfCppFound(flags, clang_cl); | |
RemoveXclangFlags(flags); | |
SkipUnusedFlags(flags, clang_cl); | |
//AppendSystemIncludes(flags); | |
return flags; | |
} | |
} // namespace LibClangSanitiser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FLAG_SANITISING | |
#define FLAG_SANITISING | |
#include <vector> | |
#include <string> | |
namepsace LibClangSanitiser { | |
std::string PrepareFlagsForLibClang(std::vector<std::string> flags); | |
} | |
#endif /* ifndef FLAG_SANITISING */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment