Hi rsmith,
MS extension: Make __noop be the integer zero, not void
We still don't accept '__noop;', and we don't consider __noop to be the
integer literal zero. More work is needed.
Form a CallExpr from __noop without parens
MSVC accepts __noop without any trailing parens and treats it like a
literal zero. We don't treat __noop as an integer literal, but now at
least we can parse a naked __noop expression.
http://reviews.llvm.org/D4476
Files:
include/clang/Basic/Builtins.def
lib/CodeGen/CGBuiltin.cpp
lib/Driver/Tools.cpp
lib/Sema/SemaExpr.cpp
test/CodeGen/builtin-ms-noop.cpp
test/Driver/sparc-float.c
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -679,7 +679,7 @@
// Microsoft builtins. These are only active with -fms-extensions.
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(__noop, "v.", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -1515,7 +1515,8 @@
return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
E->getArg(0), true);
case Builtin::BI__noop:
- return RValue::get(nullptr);
+ // __noop always evaluates to an integer literal zero.
+ return RValue::get(ConstantInt::get(IntTy, 0));
case Builtin::BI_InterlockedExchange:
case Builtin::BI_InterlockedExchangePointer:
return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1247,7 +1247,7 @@
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
- // Select the float ABI as determined by -msoft-float, -mhard-float, and
+ // Select the float ABI as determined by -msoft-float and -mhard-float.
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mhard_float)) {
@@ -2857,6 +2857,7 @@
break;
case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
AddSparcTargetArgs(Args, CmdArgs);
break;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13477,9 +13477,22 @@
case BuiltinType::PseudoObject:
return checkPseudoObjectRValue(E);
- case BuiltinType::BuiltinFn:
+ case BuiltinType::BuiltinFn: {
+ // Accept __noop without parens by implicitly converting it to a call expr.
+ auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
+ if (DRE) {
+ auto *FD = cast<FunctionDecl>(DRE->getDecl());
+ if (FD->getBuiltinID() == Builtin::BI__noop) {
+ E = ImpCastExprToType(E, Context.getPointerType(FD->getType()),
+ CK_BuiltinFnToFnPtr).get();
+ return new (Context) CallExpr(Context, E, None, Context.IntTy,
+ VK_RValue, SourceLocation());
+ }
+ }
+
Diag(E->getLocStart(), diag::err_builtin_fn_use);
return ExprError();
+ }
// Everything else should be impossible.
#define BUILTIN_TYPE(Id, SingletonId) \
Index: test/CodeGen/builtin-ms-noop.cpp
===================================================================
--- test/CodeGen/builtin-ms-noop.cpp
+++ test/CodeGen/builtin-ms-noop.cpp
@@ -1,13 +1,30 @@
-// RUN: %clang_cc1 -fms-extensions -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-class A {
- public:
+struct A {
~A() {}
};
-void f() {
-// CHECK: @_Z1fv
+extern "C" int f() {
+// CHECK: define i32 @f()
// CHECK-NOT: call void @_ZN1AD1Ev
-// CHECK: ret void
- __noop(A());
+// CHECK: ret i32 0
+ return __noop(A());
};
+
+extern "C" int g() {
+ return __noop;
+// CHECK: define i32 @g()
+// CHECK: ret i32 0
+}
+
+extern "C" int h() {
+ return (__noop);
+// CHECK: define i32 @h()
+// CHECK: ret i32 0
+}
+
+extern "C" int i() {
+ return __noop + 1;
+// CHECK: define i32 @i()
+// CHECK: ret i32 1
+}
Index: test/Driver/sparc-float.c
===================================================================
--- /dev/null
+++ test/Driver/sparc-float.c
@@ -0,0 +1,38 @@
+// Check handling -mhard-float / -msoft-float options
+// when build for SPARC platforms.
+//
+// Default sparc
+// RUN: %clang -c %s -### -o %t.o 2>&1 \
+// RUN: -target sparc-linux-gnu \
+// RUN: | FileCheck --check-prefix=CHECK-DEF %s
+// CHECK-DEF: "-msoft-float"
+//
+// -mhard-float
+// RUN: %clang -c %s -### -o %t.o 2>&1 \
+// RUN: -target sparc-linux-gnu -mhard-float \
+// RUN: | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: "-mhard-float"
+//
+// -msoft-float
+// RUN: %clang -c %s -### -o %t.o 2>&1 \
+// RUN: -target sparc-linux-gnu -msoft-float \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT %s
+// CHECK-SOFT: "-msoft-float"
+//
+// Default sparc64
+// RUN: %clang -c %s -### -o %t.o 2>&1 \
+// RUN: -target sparc64-linux-gnu \
+// RUN: | FileCheck --check-prefix=CHECK-DEF-SPARC64 %s
+// CHECK-DEF-SPARC64: "-msoft-float"
+//
+// -mhard-float
+// RUN: %clang -c %s -### -o %t.o 2>&1 \
+// RUN: -target sparc64-linux-gnu -mhard-float \
+// RUN: | FileCheck --check-prefix=CHECK-HARD-SPARC64 %s
+// CHECK-HARD-SPARC64: "-mhard-float"
+//
+// -msoft-float
+// RUN: %clang -c %s -### -o %t.o 2>&1 \
+// RUN: -target sparc64-linux-gnu -msoft-float \
+// RUN: | FileCheck --check-prefix=CHECK-SOFT-SPARC64 %s
+// CHECK-SOFT-MIPS16: "-msoft-float"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits