summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp7
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h3
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp5
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp12
-rw-r--r--clang/lib/CodeGen/TargetInfo.h6
-rw-r--r--clang/lib/Frontend/PrintPreprocessedOutput.cpp49
-rw-r--r--clang/lib/Parse/ParsePragma.cpp57
-rw-r--r--clang/lib/Parse/ParsePragma.h10
-rw-r--r--clang/lib/Parse/Parser.cpp4
-rw-r--r--clang/lib/Sema/SemaAttr.cpp6
11 files changed, 145 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 9570076574c..804af31c31d 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -183,6 +183,11 @@ namespace clang {
Gen->HandleLinkerOptionPragma(Opts);
}
+ virtual void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {
+ Gen->HandleDetectMismatch(Name, Value);
+ }
+
virtual void HandleDependentLibrary(llvm::StringRef Opts) {
Gen->HandleDependentLibrary(Opts);
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7ad08e0e0a7..3675e849aa7 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -773,6 +773,13 @@ void CodeGenModule::AppendLinkerOptions(StringRef Opts) {
LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
}
+void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) {
+ llvm::SmallString<32> Opt;
+ getTargetCodeGenInfo().getDetectMismatchOption(Name, Value, Opt);
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opt);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
void CodeGenModule::AddDependentLib(StringRef Lib) {
llvm::SmallString<24> Opt;
getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index e4e29a8d6b6..bc873166969 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -912,6 +912,9 @@ public:
/// \brief Appends Opts to the "Linker Options" metadata value.
void AppendLinkerOptions(StringRef Opts);
+ /// \bried Appends a detect mismatch command to the linker options.
+ void AddDetectMismatch(StringRef Name, StringRef Value);
+
/// \brief Appends a dependent lib to the "Linker Options" metadata value.
void AddDependentLib(StringRef Lib);
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index 56067a47bbd..763aa12aab1 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -121,6 +121,11 @@ namespace {
Builder->AppendLinkerOptions(Opts);
}
+ virtual void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {
+ Builder->AddDetectMismatch(Name, Value);
+ }
+
virtual void HandleDependentLibrary(llvm::StringRef Lib) {
Builder->AddDependentLib(Lib);
}
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 4fa0c3bbdfc..6e5084a1492 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1287,6 +1287,12 @@ public:
Opt = "/DEFAULTLIB:";
Opt += qualifyWindowsLibrary(Lib);
}
+
+ void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {
+ Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
+ }
};
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -1313,6 +1319,12 @@ public:
Opt = "/DEFAULTLIB:";
Opt += qualifyWindowsLibrary(Lib);
}
+
+ void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {
+ Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
+ }
};
}
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index dee7fd8dd40..b0ddebc1a03 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -173,6 +173,12 @@ namespace clang {
/// platform.
virtual void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const;
+
+ /// Gets the linker options necessary to detect object file mismatches on
+ /// this platform.
+ virtual void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {}
};
}
diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index 9fd36494358..83b2a271ec3 100644
--- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -140,6 +140,9 @@ public:
virtual void PragmaCaptured(SourceLocation Loc, StringRef Str);
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
const std::string &Str);
+ virtual void PragmaDetectMismatch(SourceLocation Loc,
+ const std::string &Name,
+ const std::string &Value);
virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
PragmaMessageKind Kind, StringRef Str);
virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType);
@@ -382,16 +385,8 @@ void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
setEmittedDirectiveOnThisLine();
}
-void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
- const IdentifierInfo *Kind,
+static void outputPrintable(llvm::raw_ostream& OS,
const std::string &Str) {
- startNewLineIfNeeded();
- MoveToLine(Loc);
- OS << "#pragma comment(" << Kind->getName();
-
- if (!Str.empty()) {
- OS << ", \"";
-
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
unsigned char Char = Str[i];
if (isPrintable(Char) && Char != '\\' && Char != '"')
@@ -402,6 +397,18 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
<< (char)('0'+ ((Char >> 3) & 7))
<< (char)('0'+ ((Char >> 0) & 7));
}
+}
+
+void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
+ const IdentifierInfo *Kind,
+ const std::string &Str) {
+ startNewLineIfNeeded();
+ MoveToLine(Loc);
+ OS << "#pragma comment(" << Kind->getName();
+
+ if (!Str.empty()) {
+ OS << ", \"";
+ outputPrintable(OS, Str);
OS << '"';
}
@@ -409,6 +416,19 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
setEmittedDirectiveOnThisLine();
}
+void PrintPPOutputPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
+ const std::string &Name,
+ const std::string &Value) {
+ startNewLineIfNeeded();
+ MoveToLine(Loc);
+ OS << "#pragma detect_mismatch(\"" << Name << '"';
+ outputPrintable(OS, Name);
+ OS << "\", \"";
+ outputPrintable(OS, Value);
+ OS << "\")";
+ setEmittedDirectiveOnThisLine();
+}
+
void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
StringRef Namespace,
PragmaMessageKind Kind,
@@ -430,16 +450,7 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
break;
}
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- unsigned char Char = Str[i];
- if (isPrintable(Char) && Char != '\\' && Char != '"')
- OS << (char)Char;
- else // Output anything hard as an octal escape.
- OS << '\\'
- << (char)('0'+ ((Char >> 6) & 7))
- << (char)('0'+ ((Char >> 3) & 7))
- << (char)('0'+ ((Char >> 0) & 7));
- }
+ outputPrintable(OS, Str);
OS << '"';
if (Kind == PMK_Message)
OS << ')';
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 3c6f96ac2be..10ad5df629e 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -794,6 +794,63 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
}
+/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
+///
+/// The syntax is:
+/// \code
+/// #pragma detect_mismatch("name", "value")
+/// \endcode
+/// Where 'name' and 'value' are quoted strings. The values are embedded in
+/// the object file and passed along to the linker. If the linker detects a
+/// mismatch in the object file's values for the given name, a LNK2038 error
+/// is emitted. See MSDN for more details.
+void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ SourceLocation CommentLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(CommentLoc, diag::err_expected_lparen);
+ return;
+ }
+
+ // Read the name to embed, which must be a string literal.
+ std::string NameString;
+ if (!PP.LexStringLiteral(Tok, NameString,
+ "pragma detect_mismatch",
+ /*MacroExpansion=*/true))
+ return;
+
+ // Read the comma followed by a second string literal.
+ std::string ValueString;
+ if (Tok.isNot(tok::comma)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
+ return;
+ }
+
+ if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
+ /*MacroExpansion=*/true))
+ return;
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
+ return;
+ }
+ PP.Lex(Tok); // Eat the r_paren.
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
+ return;
+ }
+
+ // If the pragma is lexically sound, notify any interested PPCallbacks.
+ if (PP.getPPCallbacks())
+ PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
+ ValueString);
+
+ Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
+}
+
/// \brief Handle the microsoft \#pragma comment extension.
///
/// The syntax is:
diff --git a/clang/lib/Parse/ParsePragma.h b/clang/lib/Parse/ParsePragma.h
index 3c6f3434ad0..b41450f4ead 100644
--- a/clang/lib/Parse/ParsePragma.h
+++ b/clang/lib/Parse/ParsePragma.h
@@ -124,6 +124,16 @@ private:
Sema &Actions;
};
+class PragmaDetectMismatchHandler : public PragmaHandler {
+public:
+ PragmaDetectMismatchHandler(Sema &Actions)
+ : PragmaHandler("detect_mismatch"), Actions(Actions) {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+private:
+ Sema &Actions;
+};
+
} // end namespace clang
#endif
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 3124b96455e..f19d24299aa 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -105,6 +105,8 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
if (getLangOpts().MicrosoftExt) {
MSCommentHandler.reset(new PragmaCommentHandler(actions));
PP.AddPragmaHandler(MSCommentHandler.get());
+ MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions));
+ PP.AddPragmaHandler(MSDetectMismatchHandler.get());
}
CommentSemaHandler.reset(new ActionCommentHandler(actions));
@@ -444,6 +446,8 @@ Parser::~Parser() {
if (getLangOpts().MicrosoftExt) {
PP.RemovePragmaHandler(MSCommentHandler.get());
MSCommentHandler.reset();
+ PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
+ MSDetectMismatchHandler.reset();
}
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 943054be340..3fbb11f2fde 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -283,6 +283,12 @@ void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, llvm::StringRef Arg) {
llvm_unreachable("invalid pragma comment kind");
}
+void Sema::ActOnPragmaDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {
+ // FIXME: Serialize this.
+ Consumer.HandleDetectMismatch(Name, Value);
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
OpenPOWER on IntegriCloud