diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index dbb5dde20a2b9..5463b7dfc18ce 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -1025,6 +1025,7 @@ LIBBUILTIN(pthread_create, "", "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES) // POSIX setjmp.h +// FIXME: MinGW _setjmp has an additional void* parameter. LIBBUILTIN(_setjmp, "iJ", "fjT", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(__sigsetjmp, "iSJi", "fjT", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(sigsetjmp, "iSJi", "fjT", "setjmp.h", ALL_LANGUAGES) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 8994b939093e5..6b93f1b60af52 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3754,11 +3754,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI_abnormal_termination: return RValue::get(EmitSEHAbnormalTermination()); case Builtin::BI_setjmpex: - if (getTarget().getTriple().isOSMSVCRT()) + if (getTarget().getTriple().isOSMSVCRT() && E->getNumArgs() == 1 && + E->getArg(0)->getType()->isPointerType()) return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E); break; case Builtin::BI_setjmp: - if (getTarget().getTriple().isOSMSVCRT()) { + if (getTarget().getTriple().isOSMSVCRT() && E->getNumArgs() == 1 && + E->getArg(0)->getType()->isPointerType()) { if (getTarget().getTriple().getArch() == llvm::Triple::x86) return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp3, E); else if (getTarget().getTriple().getArch() == llvm::Triple::aarch64) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b00d2ff5f1d59..1bf04d9cb4f27 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1573,11 +1573,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinSetjmp(TheCall)) return ExprError(); break; - case Builtin::BI_setjmp: - case Builtin::BI_setjmpex: - if (checkArgCount(*this, TheCall, 1)) - return true; - break; case Builtin::BI__builtin_classify_type: if (checkArgCount(*this, TheCall, 1)) return true; TheCall->setType(Context.IntTy); diff --git a/clang/test/Sema/builtin-setjmp.c b/clang/test/Sema/builtin-setjmp.c index 6a114fad05d9d..604d534eb504a 100644 --- a/clang/test/Sema/builtin-setjmp.c +++ b/clang/test/Sema/builtin-setjmp.c @@ -1,34 +1,47 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DNO_JMP_BUF %s -ast-dump | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DWRONG_JMP_BUF %s -ast-dump | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DRIGHT_JMP_BUF %s -ast-dump | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DONLY_JMP_BUF %s -ast-dump | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DNO_SETJMP %s -ast-dump 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DNO_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DWRONG_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DRIGHT_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DONLY_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=c,expected -DNO_SETJMP %s -ast-dump 2>&1 | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DNO_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DWRONG_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DRIGHT_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK1,CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DONLY_JMP_BUF %s -ast-dump | FileCheck %s --check-prefixes=CHECK2 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify=cxx,expected -x c++ -DNO_SETJMP %s -ast-dump | FileCheck %s --check-prefixes=CHECK2 + +#ifdef __cplusplus +extern "C" { +#endif #ifdef NO_JMP_BUF // This happens in some versions of glibc: the declaration of __sigsetjmp // precedes the declaration of sigjmp_buf. extern long setjmp(long *); // Can't check, so we trust that this is the right type // FIXME: We could still diagnose the missing `jmp_buf` at the point of the call. -// expected-no-diagnostics +// c-no-diagnostics #elif WRONG_JMP_BUF typedef long jmp_buf; -extern int setjmp(char); // expected-warning {{incompatible redeclaration of library function 'setjmp'}} - // expected-note@-1 {{'setjmp' is a builtin with type 'int (jmp_buf)' (aka 'int (long)')}} +// FIXME: Consider producing a similar warning in C++. +extern int setjmp(char); // c-warning {{incompatible redeclaration of library function 'setjmp'}} + // c-note@-1 {{'setjmp' is a builtin with type 'int (jmp_buf)' (aka 'int (long)')}} #elif RIGHT_JMP_BUF typedef long jmp_buf; extern int setjmp(long); // OK, right type. -// expected-no-diagnostics #elif ONLY_JMP_BUF typedef int *jmp_buf; #endif void use() { setjmp(0); - #ifdef NO_SETJMP - // expected-warning@-2 {{implicit declaration of function 'setjmp' is invalid in C99}} + #if NO_SETJMP + // cxx-error@-2 {{undeclared identifier 'setjmp'}} + // c-warning@-3 {{implicit declaration of function 'setjmp' is invalid in C99}} #elif ONLY_JMP_BUF - // expected-warning@-4 {{implicitly declaring library function 'setjmp' with type 'int (jmp_buf)' (aka 'int (int *)')}} - // expected-note@-5 {{include the header or explicitly provide a declaration for 'setjmp'}} + // cxx-error@-5 {{undeclared identifier 'setjmp'}} + // c-warning@-6 {{implicitly declaring library function 'setjmp' with type 'int (jmp_buf)' (aka 'int (int *)')}} + // c-note@-7 {{include the header or explicitly provide a declaration for 'setjmp'}} + #else + // cxx-no-diagnostics #endif #ifdef NO_SETJMP @@ -37,6 +50,24 @@ void use() { #endif } -// CHECK: FunctionDecl {{.*}} used setjmp -// CHECK: BuiltinAttr {{.*}} Implicit -// CHECK: ReturnsTwiceAttr {{.*}} Implicit +// CHECK1: FunctionDecl {{.*}} used setjmp +// CHECK1: BuiltinAttr {{.*}} Implicit +// CHECK1: ReturnsTwiceAttr {{.*}} Implicit + +// mingw declares _setjmp with an unusual signature. +int _setjmp(void *, void *); +#if !defined(NO_JMP_BUF) && !defined(NO_SETJMP) +// c-warning@-2 {{incompatible redeclaration of library function '_setjmp'}} +// c-note@-3 {{'_setjmp' is a builtin with type 'int (jmp_buf)'}} +#endif +void use_mingw() { + _setjmp(0, 0); +} + +// CHECK2: FunctionDecl {{.*}} used _setjmp +// CHECK2: BuiltinAttr {{.*}} Implicit +// CHECK2: ReturnsTwiceAttr {{.*}} Implicit + +#ifdef __cplusplus +} +#endif