]> granicus.if.org Git - clang/commitdiff
Semantic analysis and CodeGen support for C11's _Noreturn. This is modeled as
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Jan 2013 05:45:05 +0000 (05:45 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Jan 2013 05:45:05 +0000 (05:45 +0000)
an attribute for consistency with our other noreturn mechanisms.

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

include/clang/Basic/Attr.td
lib/AST/Decl.cpp
lib/CodeGen/CGCall.cpp
lib/Sema/SemaDecl.cpp
test/CodeGen/function-attributes.c
test/Sema/return-noreturn.c

index 786b43a77bdff9719fbf5a92d63a711fb4276674..52ebbb41db85ec8815f6b000eaf58f9ce2a85c02 100644 (file)
@@ -303,6 +303,12 @@ def CUDAShared : InheritableAttr {
   let Spellings = [GNU<"shared">];
 }
 
+def C11NoReturn : InheritableAttr {
+  let Spellings = [Keyword<"_Noreturn">];
+  let Subjects = [Function];
+  let SemaHandler = 0;
+}
+
 def CXX11NoReturn : InheritableAttr {
   let Spellings = [CXX11<"","noreturn">, CXX11<"std","noreturn">];
   let Subjects = [Function];
index f9ad9461095294a3106ff2ea1b1fb7592455e342..ed2a0c36fd20438a4909acb734bb02aa454729ed 100644 (file)
@@ -1812,6 +1812,7 @@ bool FunctionDecl::isGlobal() const {
 
 bool FunctionDecl::isNoReturn() const {
   return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
+         hasAttr<C11NoReturnAttr>() ||
          getType()->getAs<FunctionType>()->getNoReturnAttr();
 }
 
index c29230f75bf8450fa323a1eb2e494e84d0d55287..e7b543a78cfe7c5cc0ef95335e3bb5a715648f93 100644 (file)
@@ -983,19 +983,17 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
       FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice);
     if (TargetDecl->hasAttr<NoThrowAttr>())
       FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
-    else if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
+    if (TargetDecl->hasAttr<NoReturnAttr>())
+      FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
+
+    if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
       const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
       if (FPT && FPT->isNothrow(getContext()))
         FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+      if (Fn->isNoReturn())
+        FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
     }
 
-    if (TargetDecl->hasAttr<NoReturnAttr>() ||
-        TargetDecl->hasAttr<CXX11NoReturnAttr>())
-      FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
-
-    if (TargetDecl->hasAttr<ReturnsTwiceAttr>())
-      FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice);
-
     // 'const' and 'pure' attribute functions are also nounwind.
     if (TargetDecl->hasAttr<ConstAttr>()) {
       FuncAttrs.addAttribute(llvm::Attribute::ReadNone);
index 2c09c88b2010a575cfaf730a5a09cfdc88c7fc4a..c94bf5f092f89a4f5f3e26d49ee5efad1103472f 100644 (file)
@@ -1900,6 +1900,11 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
       ++I;
       continue; // regular attr merging will take care of validating this.
     }
+    // C's _Noreturn is allowed to be added to a function after it is defined.
+    if (isa<C11NoReturnAttr>(NewAttribute)) {
+      ++I;
+      continue;
+    }
     S.Diag(NewAttribute->getLocation(),
            diag::warn_attribute_precede_definition);
     S.Diag(Def->getLocation(), diag::note_previous_definition);
@@ -5889,6 +5894,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope);
   DeclsInPrototypeScope.clear();
 
+  if (D.getDeclSpec().isNoreturnSpecified())
+    NewFD->addAttr(
+        ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
+                                       Context));
+
   // Process the non-inheritable attributes on this declaration.
   ProcessDeclAttributes(S, NewFD, D,
                         /*NonInheritable=*/true, /*Inheritable=*/false);
index 6cbf40ba220f1a3bdc4df683c50764d5dbdd2b58..886bd8d2fb515baeb14c4a61ba9bf149da9f2818 100644 (file)
@@ -32,10 +32,16 @@ void __attribute__((always_inline)) f8(void) { }
 
 // CHECK: call void @f9_t()
 // CHECK: noreturn
-// CHECK: {
+// CHECK: }
 void __attribute__((noreturn)) f9_t(void);
 void f9(void) { f9_t(); }
 
+// CHECK: call void @f9a()
+// CHECK: noreturn
+// CHECK: }
+_Noreturn void f9a(void);
+void f9b(void) { f9a(); }
+
 // FIXME: We should be setting nounwind on calls.
 // CHECK: call i32 @f10_t()
 // CHECK: readnone
index 5dd6693373aa18fdf444605f46ea1c6020a7ed32..6d521eb017cb8499ca609307436aebb0f7d3695b 100644 (file)
@@ -36,7 +36,7 @@ test4() {
   test2_positive();
 }
 
-// FIXME: do not warn here.
-_Noreturn void test5() { // expected-warning {{could be declared with attribute 'noreturn'}}
+// Do not warn here.
+_Noreturn void test5() {
   test2_positive();
 }