mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
Semantic analysis and CodeGen support for C11's _Noreturn. This is modeled as
an attribute for consistency with our other noreturn mechanisms. llvm-svn: 173898
This commit is contained in:
parent
457a77739b
commit
debc59d1f3
@ -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];
|
||||
|
@ -1812,6 +1812,7 @@ bool FunctionDecl::isGlobal() const {
|
||||
|
||||
bool FunctionDecl::isNoReturn() const {
|
||||
return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
|
||||
hasAttr<C11NoReturnAttr>() ||
|
||||
getType()->getAs<FunctionType>()->getNoReturnAttr();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user