diff options
| author | Rui Ueyama <ruiu@google.com> | 2013-07-25 01:23:50 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2013-07-25 01:23:50 +0000 |
| commit | 1e3e8752a8f72bec0de34e44478a7e9e5f2ea982 (patch) | |
| tree | d7948b34292114021095258216c75329130b5df5 | |
| parent | 886a3e2cdf9d2da450007f0794c98bc3f1ebb5d0 (diff) | |
| download | bcm5719-llvm-1e3e8752a8f72bec0de34e44478a7e9e5f2ea982.tar.gz bcm5719-llvm-1e3e8752a8f72bec0de34e44478a7e9e5f2ea982.zip | |
[PECOFF] Add /failifmismatch option.
llvm-svn: 187095
| -rw-r--r-- | lld/lib/Driver/WinLinkDriver.cpp | 38 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkOptions.td | 4 | ||||
| -rw-r--r-- | lld/unittests/DriverTests/WinLinkDriverTest.cpp | 11 |
3 files changed, 53 insertions, 0 deletions
diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 15197b7c619..6befd29df11 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -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), diff --git a/lld/lib/Driver/WinLinkOptions.td b/lld/lib/Driver/WinLinkOptions.td index 5a44d342c71..1456a6bd70e 100644 --- a/lld/lib/Driver/WinLinkOptions.td +++ b/lld/lib/Driver/WinLinkOptions.td @@ -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>; diff --git a/lld/unittests/DriverTests/WinLinkDriverTest.cpp b/lld/unittests/DriverTests/WinLinkDriverTest.cpp index 6b2f7db695c..6d5ae05ee7b 100644 --- a/lld/unittests/DriverTests/WinLinkDriverTest.cpp +++ b/lld/unittests/DriverTests/WinLinkDriverTest.cpp @@ -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 |

