]> granicus.if.org Git - clang/commitdiff
Add returns_twice to functions that are known to return twice. This implements
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 12 Oct 2011 19:51:18 +0000 (19:51 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 12 Oct 2011 19:51:18 +0000 (19:51 +0000)
the same behavior of gcc by keeping the attribute out of the function type.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141803 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Builtins.def
include/clang/Basic/Builtins.h
lib/AST/DeclPrinter.cpp
lib/CodeGen/CGCall.cpp
lib/Sema/SemaDecl.cpp
test/Analysis/security-syntax-checks.m
test/CodeGen/function-attributes.c
test/Sema/attr-returns-twice.c [new file with mode: 0644]

index 60bcde372ac95c652756cddf044fd49438a53fcd..d3a5eaf5f9753e1d5c04f5a18a7926e619423205 100644 (file)
@@ -77,6 +77,7 @@
 //          in that it accepts its arguments as a va_list rather than
 //          through an ellipsis
 //  e -> const, but only when -fmath-errno=0
+//  j -> returns_twice (like setjmp)
 //  FIXME: gcc has nonnull
 
 #if defined(BUILTIN) && !defined(LIBBUILTIN)
@@ -427,7 +428,7 @@ BUILTIN(__builtin_return_address, "v*IUi", "n")
 BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
 BUILTIN(__builtin_frame_address, "v*IUi", "n")
 BUILTIN(__builtin_flt_rounds, "i", "nc")
-BUILTIN(__builtin_setjmp, "iv**", "")
+BUILTIN(__builtin_setjmp, "iv**", "j")
 BUILTIN(__builtin_longjmp, "vv**i", "r")
 BUILTIN(__builtin_unwind_init, "v", "")
 BUILTIN(__builtin_eh_return_data_regno, "iIi", "nc")
@@ -672,6 +673,17 @@ LIBBUILTIN(bzero, "vv*z",         "f",     "strings.h", ALL_LANGUAGES)
 // POSIX unistd.h
 LIBBUILTIN(_exit, "vi",           "fr",    "unistd.h", ALL_LANGUAGES)
 // POSIX setjmp.h
+
+LIBBUILTIN(_setjmp, "iJ",         "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(__sigsetjmp, "iJ",     "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(setjmp, "iJ",          "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(sigsetjmp, "iJ",       "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(setjmp_syscall, "iJ",  "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(savectx, "iJ",         "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(qsetjmp, "iJ",         "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(vfork, "iJ",           "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(getcontext, "iJ",      "fj",   "setjmp.h", ALL_LANGUAGES)
+
 LIBBUILTIN(_longjmp, "vJi",       "fr",    "setjmp.h", ALL_LANGUAGES)
 LIBBUILTIN(siglongjmp, "vSJi",    "fr",    "setjmp.h", ALL_LANGUAGES)
 // non-standard but very common
index fbf4ef417fff2b0ab0923cc6631795df80393515..5afa02010040c780db1a1fa14699a296c4cd528f 100644 (file)
@@ -103,6 +103,11 @@ public:
     return strchr(GetRecord(ID).Attributes, 'r') != 0;
   }
 
+  /// isReturnsTwice - Return true if we know this builtin can return twice.
+  bool isReturnsTwice(unsigned ID) const {
+    return strchr(GetRecord(ID).Attributes, 'j') != 0;
+  }
+
   /// isLibFunction - Return true if this is a builtin for a libc/libm function,
   /// with a "__builtin_" prefix (e.g. __builtin_abs).
   bool isLibFunction(unsigned ID) const {
index 73f5cdb12223e846842050e52c16188d5fd20fe7..4f3e8ad2d5a93e9eb7f959a1992f630a575c1202 100644 (file)
@@ -468,6 +468,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
 
     if (D->hasAttr<NoReturnAttr>())
       Proto += " __attribute((noreturn))";
+
+    if (D->hasAttr<ReturnsTwiceAttr>())
+      Proto += " __attribute((returns_twice))";
+
     if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
       bool HasInitializerList = false;
       for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
index f52abef3306b2eca8c7e944a709f5b1bdc5c03b9..6ae2d0c967751d38867e9425c9dcd5044891b124 100644 (file)
@@ -729,6 +729,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
 
   // FIXME: handle sseregparm someday...
   if (TargetDecl) {
+    if (TargetDecl->hasAttr<ReturnsTwiceAttr>())
+      FuncAttrs |= llvm::Attribute::ReturnsTwice;
     if (TargetDecl->hasAttr<NoThrowAttr>())
       FuncAttrs |= llvm::Attribute::NoUnwind;
     else if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
index d19023d04553746b716e59c7d4dca686f7dd46c0..8e2ff5ca881a55b5ac4870f432e10956c76ff683 100644 (file)
@@ -7263,6 +7263,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
         FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
     }
 
+    if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
+        !FD->getAttr<ReturnsTwiceAttr>())
+      FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context));
     if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr<NoThrowAttr>())
       FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
     if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>())
index a04401b531f5f5c230eb46d24ab7238fb8b59a10..6fb5b3cf14ef465761f9491fc87e38d24e6e1beb 100644 (file)
@@ -170,7 +170,7 @@ void test_strcat() {
 //===----------------------------------------------------------------------===
 typedef int __int32_t;
 typedef __int32_t pid_t;
-pid_t vfork(void);
+pid_t vfork(void); //expected-warning{{declaration of built-in function 'vfork' requires inclusion of the header <setjmp.h>}}
 
 void test_vfork() {
   vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process.}}
index fd98458c8426af2ac78002c5c9367481c849deda..6cbf40ba220f1a3bdc4df683c50764d5dbdd2b58 100644 (file)
@@ -100,3 +100,14 @@ __attribute__ ((returns_twice)) void f17(void);
 __attribute__ ((returns_twice)) void f18(void) {
         f17();
 }
+
+// CHECK: define void @f19()
+// CHECK: {
+// CHECK: call i32 @setjmp(i32* null)
+// CHECK: returns_twice
+// CHECK: ret void
+typedef int jmp_buf[((9 * 2) + 3 + 16)];
+int setjmp(jmp_buf);
+void f19(void) {
+  setjmp(0);
+}
diff --git a/test/Sema/attr-returns-twice.c b/test/Sema/attr-returns-twice.c
new file mode 100644 (file)
index 0000000..13f53e3
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+int a __attribute__((returns_twice)); // expected-warning {{'returns_twice' attribute only applies to functions}}
+
+__attribute__((returns_twice)) void t0(void) {
+}
+
+void t1() __attribute__((returns_twice));
+
+void t2() __attribute__((returns_twice(2))); // expected-error {{attribute takes no arguments}}
+
+typedef void (*t3)(void) __attribute__((returns_twice)); // expected-warning {{'returns_twice' attribute only applies to functions}}