summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2013-07-25 01:23:50 +0000
committerRui Ueyama <ruiu@google.com>2013-07-25 01:23:50 +0000
commit1e3e8752a8f72bec0de34e44478a7e9e5f2ea982 (patch)
treed7948b34292114021095258216c75329130b5df5
parent886a3e2cdf9d2da450007f0794c98bc3f1ebb5d0 (diff)
downloadbcm5719-llvm-1e3e8752a8f72bec0de34e44478a7e9e5f2ea982.tar.gz
bcm5719-llvm-1e3e8752a8f72bec0de34e44478a7e9e5f2ea982.zip
[PECOFF] Add /failifmismatch option.
llvm-svn: 187095
-rw-r--r--lld/lib/Driver/WinLinkDriver.cpp38
-rw-r--r--lld/lib/Driver/WinLinkOptions.td4
-rw-r--r--lld/unittests/DriverTests/WinLinkDriverTest.cpp11
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
OpenPOWER on IntegriCloud