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(), 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(E->IgnoreParenImpCasts()); + if (DRE) { + auto *FD = cast(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"