[PECOFF] Add /failifmismatch option.

llvm-svn: 187095
This commit is contained in:
Rui Ueyama 2013-07-25 01:23:50 +00:00
parent 886a3e2cdf
commit 1e3e8752a8
3 changed files with 53 additions and 0 deletions

View File

@ -15,6 +15,7 @@
#include <cstdlib>
#include <sstream>
#include <map>
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@ -215,6 +216,26 @@ std::vector<StringRef> splitPathList(StringRef str) {
return std::move(ret);
}
// Handle /failifmatch option.
bool handleFailIfMismatchOption(StringRef option,
std::map<StringRef, StringRef> &mustMatch,
raw_ostream &diagnostics) {
StringRef key, value;
llvm::tie(key, value) = option.split('=');
if (key.empty() || value.empty()) {
diagnostics << "error: malformed /failifmatch option: " << option << "\n";
return false;
}
auto it = mustMatch.find(key);
if (it != mustMatch.end() && it->second != value) {
diagnostics << "error: mismatch detected: '" << it->second << "' and '"
<< value << "' for key '" << key << "'\n";
return false;
}
mustMatch[key] = value;
return true;
}
// Process "LINK" environment variable. If defined, the value of the variable
// should be processed as command line arguments.
std::vector<const char *> processLinkEnv(PECOFFTargetInfo &info,
@ -367,6 +388,23 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
defaultLibs.push_back((*it)->getValue());
}
// Handle /failifmismatch. /failifmismatch is the hidden linker option behind
// the scenes of "detect_mismatch" pragma. If the compiler finds "#pragma
// detect_mismatch(name, value)", it outputs "/failifmismatch:name=value" to
// the .drectve section of the resultant object file. The linker raises an
// error if conflicting /failmismatch options are given. Conflicting options
// are the options with the same key but with different values.
//
// This feature is used to prevent inconsistent object files from linking.
std::map<StringRef, StringRef> mustMatch;
for (llvm::opt::arg_iterator
it = parsedArgs->filtered_begin(OPT_failifmismatch),
ie = parsedArgs->filtered_end();
it != ie; ++it) {
if (!handleFailIfMismatchOption((*it)->getValue(), mustMatch, diagnostics))
return true;
}
// Add input files
std::vector<StringRef> inputPaths;
for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),

View File

@ -59,5 +59,9 @@ def incl : _Separate<"include">,
HelpText<"Force symbol to be added to symbol table as undefined one">;
def incl_c : _Joined<"include:", incl>;
// No help text because /failifmismatch is not intended to be used by the user.
def failifmismatch : _Separate<"failifmismatch">;
def failifmismatch_c : _Joined<"failifmismatch:", failifmismatch>;
def help : _Flag<"help">;
def help_q : _Flag<"?">, Alias<help>;

View File

@ -187,4 +187,15 @@ TEST_F(WinLinkParserTest, NoInputFiles) {
EXPECT_EQ("No input files\n", errorMessage());
}
TEST_F(WinLinkParserTest, FailIfMismatch_Match) {
EXPECT_FALSE(parse("link.exe", "/failifmismatch:foo=bar",
"/failifmismatch:foo=bar", "/failifmismatch:abc=def",
"a.out", nullptr));
}
TEST_F(WinLinkParserTest, FailIfMismatch_Mismatch) {
EXPECT_TRUE(parse("link.exe", "/failifmismatch:foo=bar",
"/failifmismatch:foo=baz", "a.out", nullptr));
}
} // end anonymous namespace