diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Headers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Headers/stdnoreturn.h | 30 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 11 |
5 files changed, 55 insertions, 3 deletions
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 25e4d903bb7..ae689c37fae 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -27,6 +27,7 @@ set(files stdbool.h stddef.h stdint.h + stdnoreturn.h tgmath.h tmmintrin.h varargs.h diff --git a/clang/lib/Headers/stdnoreturn.h b/clang/lib/Headers/stdnoreturn.h new file mode 100644 index 00000000000..a7a301d7e0b --- /dev/null +++ b/clang/lib/Headers/stdnoreturn.h @@ -0,0 +1,30 @@ +/*===---- stdnoreturn.h - Standard header for noreturn macro ---------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __STDNORETURN_H +#define __STDNORETURN_H + +#define noreturn _Noreturn +#define __noreturn_is_defined 1 + +#endif /* __STDNORETURN_H */ diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 74769bf7319..f9c68c79b9c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2619,6 +2619,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw_explicit: isInvalid = DS.setFunctionSpecExplicit(Loc); break; + case tok::kw__Noreturn: + if (!getLangOpts().C11) + Diag(Loc, diag::ext_c11_noreturn); + isInvalid = DS.setFunctionSpecNoreturn(Loc); + break; // alignment-specifier case tok::kw__Alignas: @@ -3878,6 +3883,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_inline: case tok::kw_virtual: case tok::kw_explicit: + case tok::kw__Noreturn: // friend keyword. case tok::kw_friend: diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index fa63c2af38f..35b0736196a 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -329,7 +329,8 @@ unsigned DeclSpec::getParsedSpecifiers() const { if (hasTypeSpecifier()) Res |= PQ_TypeSpecifier; - if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified) + if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified || + FS_noreturn_specified) Res |= PQ_FunctionSpecifier; return Res; } @@ -734,6 +735,13 @@ bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc) { return false; } +bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc) { + // '_Noreturn _Noreturn' is ok. + FS_noreturn_specified = true; + FS_noreturnLoc = Loc; + return false; +} + bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (Friend_specified) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a13d8b3b462..9cf5e73665a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4097,6 +4097,10 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { if (D.getDeclSpec().isExplicitSpecified()) Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_non_function); + + if (D.getDeclSpec().isNoreturnSpecified()) + Diag(D.getDeclSpec().getNoreturnSpecLoc(), + diag::err_noreturn_non_function); } NamedDecl* @@ -6429,9 +6433,10 @@ static SourceRange getResultSourceRange(const FunctionDecl *FD) { void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { // C++11 [basic.start.main]p3: A program that declares main to be inline, // static or constexpr is ill-formed. - // C99 6.7.4p4: In a hosted environment, the inline function specifier - // shall not appear in a declaration of main. + // C11 6.7.4p4: In a hosted environment, no function specifier(s) shall + // appear in a declaration of main. // static main is not an error under C99, but we should warn about it. + // We accept _Noreturn main as an extension. if (FD->getStorageClass() == SC_Static) Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus ? diag::err_static_main : diag::warn_static_main) @@ -6439,6 +6444,8 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { if (FD->isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_main) << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); + if (DS.isNoreturnSpecified()) + Diag(DS.getNoreturnSpecLoc(), diag::ext_noreturn_main); if (FD->isConstexpr()) { Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); |