r173898 - Semantic analysis and CodeGen support for C11's _Noreturn. This is modeled as

Richard Smith richard-llvm at metafoo.co.uk
Tue Jan 29 21:45:05 PST 2013


Author: rsmith
Date: Tue Jan 29 23:45:05 2013
New Revision: 173898

URL: http://llvm.org/viewvc/llvm-project?rev=173898&view=rev
Log:
Semantic analysis and CodeGen support for C11's _Noreturn. This is modeled as
an attribute for consistency with our other noreturn mechanisms.

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

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=173898&r1=173897&r2=173898&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Jan 29 23:45:05 2013
@@ -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];

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=173898&r1=173897&r2=173898&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Jan 29 23:45:05 2013
@@ -1812,6 +1812,7 @@ bool FunctionDecl::isGlobal() const {
 
 bool FunctionDecl::isNoReturn() const {
   return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
+         hasAttr<C11NoReturnAttr>() ||
          getType()->getAs<FunctionType>()->getNoReturnAttr();
 }
 

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=173898&r1=173897&r2=173898&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Jan 29 23:45:05 2013
@@ -983,19 +983,17 @@ void CodeGenModule::ConstructAttributeLi
       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);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=173898&r1=173897&r2=173898&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan 29 23:45:05 2013
@@ -1900,6 +1900,11 @@ static void checkNewAttributesAfterDef(S
       ++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, 
   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);

Modified: cfe/trunk/test/CodeGen/function-attributes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/function-attributes.c?rev=173898&r1=173897&r2=173898&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/function-attributes.c (original)
+++ cfe/trunk/test/CodeGen/function-attributes.c Tue Jan 29 23:45:05 2013
@@ -32,10 +32,16 @@ void __attribute__((always_inline)) f8(v
 
 // 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

Modified: cfe/trunk/test/Sema/return-noreturn.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/return-noreturn.c?rev=173898&r1=173897&r2=173898&view=diff
==============================================================================
--- cfe/trunk/test/Sema/return-noreturn.c (original)
+++ cfe/trunk/test/Sema/return-noreturn.c Tue Jan 29 23:45:05 2013
@@ -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();
 }





More information about the cfe-commits mailing list