summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/Builtins.def1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/CodeGen/CGBuiltin.cpp23
-rw-r--r--lib/Sema/SemaChecking.cpp26
-rw-r--r--test/CodeGen/ms-annotation.c26
-rw-r--r--test/Sema/ms-annotation.c13
6 files changed, 91 insertions, 0 deletions
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 724a8bf6b2..8941fc5daa 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -732,6 +732,7 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
// Microsoft builtins. These are only active with -fms-extensions.
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c41e19dbe4..30f1528fec 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7902,6 +7902,8 @@ def err_builtin_annotation_first_arg : Error<
"first argument to __builtin_annotation must be an integer">;
def err_builtin_annotation_second_arg : Error<
"second argument to __builtin_annotation must be a non-wide string constant">;
+def err_msvc_annotation_wide_str : Error<
+ "arguments to __annotation must be wide string constants">;
// CFString checking
def err_cfstring_literal_not_string_constant : Error<
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 1923c58729..71705146a1 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -30,6 +30,7 @@
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/Support/ConvertUTF.h"
#include <sstream>
using namespace clang;
@@ -1953,6 +1954,28 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Builder.CreateZExt(EmitSignBit(*this, EmitScalarExpr(E->getArg(0))),
ConvertType(E->getType())));
}
+ case Builtin::BI__annotation: {
+ // Re-encode each wide string to UTF8 and make an MDString.
+ SmallVector<Metadata *, 1> Strings;
+ for (const Expr *Arg : E->arguments()) {
+ const auto *Str = cast<StringLiteral>(Arg->IgnoreParenCasts());
+ assert(Str->getCharByteWidth() == 2);
+ StringRef WideBytes = Str->getBytes();
+ std::string StrUtf8;
+ if (!convertUTF16ToUTF8String(
+ makeArrayRef(WideBytes.data(), WideBytes.size()), StrUtf8)) {
+ CGM.ErrorUnsupported(E, "non-UTF16 __annotation argument");
+ continue;
+ }
+ Strings.push_back(llvm::MDString::get(getLLVMContext(), StrUtf8));
+ }
+
+ // Build and MDTuple of MDStrings and emit the intrinsic call.
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::label_annotation, {});
+ MDTuple *StrTuple = MDTuple::get(getLLVMContext(), Strings);
+ Builder.CreateCall(F, MetadataAsValue::get(getLLVMContext(), StrTuple));
+ return RValue::getIgnored();
+ }
case Builtin::BI__builtin_annotation: {
llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0));
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::annotation,
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 31700e7893..7b0f72fd99 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -99,6 +99,28 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
return false;
}
+static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) {
+ // We need at least one argument.
+ if (TheCall->getNumArgs() < 1) {
+ S.Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return true;
+ }
+
+ // All arguments should be wide string literals.
+ for (Expr *Arg : TheCall->arguments()) {
+ auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts());
+ if (!Literal || !Literal->isWide()) {
+ S.Diag(Arg->getLocStart(), diag::err_msvc_annotation_wide_str)
+ << Arg->getSourceRange();
+ return true;
+ }
+ }
+
+ return false;
+}
+
/// Check that the argument to __builtin_addressof is a glvalue, and set the
/// result type to the corresponding pointer type.
static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
@@ -1000,6 +1022,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI##ID: \
return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID);
#include "clang/Basic/Builtins.def"
+ case Builtin::BI__annotation:
+ if (SemaBuiltinMSVCAnnotation(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_annotation:
if (SemaBuiltinAnnotation(*this, TheCall))
return ExprError();
diff --git a/test/CodeGen/ms-annotation.c b/test/CodeGen/ms-annotation.c
new file mode 100644
index 0000000000..4459fc032a
--- /dev/null
+++ b/test/CodeGen/ms-annotation.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple i686-windows %s -fms-extensions -emit-llvm -o - | FileCheck %s
+//
+// Test that LLVM optimizations leave these intrinsics alone, for the most part.
+// RUN: %clang_cc1 -O2 -triple i686-windows %s -fms-extensions -emit-llvm -o - | FileCheck %s
+
+void test1(void) {
+ __annotation(L"a1");
+ __annotation(L"a1", L"a2");
+ __annotation(L"a1", L"a2", L"a3");
+ __annotation(L"multi " L"part " L"string");
+ __annotation(L"unicode: \u0ca0_\u0ca0");
+}
+
+// CHECK-LABEL: define void @test1()
+// CHECK: call void @llvm.label.annotation(metadata ![[A1:[0-9]+]])
+// CHECK: call void @llvm.label.annotation(metadata ![[A2:[0-9]+]])
+// CHECK: call void @llvm.label.annotation(metadata ![[A3:[0-9]+]])
+// CHECK: call void @llvm.label.annotation(metadata ![[A4:[0-9]+]])
+// CHECK: call void @llvm.label.annotation(metadata ![[A5:[0-9]+]])
+// CHECK: ret void
+
+// CHECK: ![[A1]] = !{!"a1"}
+// CHECK: ![[A2]] = !{!"a1", !"a2"}
+// CHECK: ![[A3]] = !{!"a1", !"a2", !"a3"}
+// CHECK: ![[A4]] = !{!"multi part string"}
+// CHECK: ![[A5]] = !{!"unicode: \E0\B2\A0_\E0\B2\A0"}
diff --git a/test/Sema/ms-annotation.c b/test/Sema/ms-annotation.c
new file mode 100644
index 0000000000..9a2beebf06
--- /dev/null
+++ b/test/Sema/ms-annotation.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple i686-windows %s -verify -fms-extensions
+// RUN: %clang_cc1 -x c++ -std=c++11 -triple i686-windows %s -verify -fms-extensions
+// RUN: %clang_cc1 -x c++ -std=c++14 -triple i686-windows %s -verify -fms-extensions
+
+void test1(void) {
+ __annotation(); // expected-error {{too few arguments to function call, expected at least 1, have 0}}
+ __annotation(1); // expected-error {{must be wide string constants}}
+ __annotation(L"a1");
+ __annotation(L"a1", L"a2");
+ __annotation(L"a1", L"a2", 42); // expected-error {{must be wide string constants}}
+ __annotation(L"a1", L"a2", L"a3");
+ __annotation(L"multi " L"part " L"string");
+}