mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-15 22:16:30 +00:00
[Clang] add ext warning for missing return in 'main' for C89 mode (#134617)
Fixes #21650 --- Clang currently inserts an implicit `return 0;` in `main()` when compiling in `C89` mode, even though the `C89` standard doesn't require this behavior. This patch changes that behavior by emitting a warning instead of silently inserting the implicit return under `-pedantic`.
This commit is contained in:
parent
156e2532ed
commit
9f463056e6
@ -321,6 +321,7 @@ Improvements to Clang's diagnostics
|
||||
|
||||
- ``-Wc++98-compat`` no longer diagnoses use of ``__auto_type`` or
|
||||
``decltype(auto)`` as though it was the extension for ``auto``. (#GH47900)
|
||||
- Clang now issues a warning for missing return in ``main`` in C89 mode. (#GH21650)
|
||||
|
||||
- Now correctly diagnose a tentative definition of an array with static
|
||||
storage duration in pedantic mode in C. (#GH50661)
|
||||
|
@ -1031,6 +1031,9 @@ def err_mainlike_template_decl : Error<"%0 cannot be a template">;
|
||||
def err_main_returns_nonint : Error<"'main' must return 'int'">;
|
||||
def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">,
|
||||
InGroup<MainReturnType>;
|
||||
def ext_main_no_return : Extension<
|
||||
"implicit '0' return value from 'main' is a C99 extension">,
|
||||
InGroup<MainReturnType>;
|
||||
def note_main_change_return_type : Note<"change return type to 'int'">;
|
||||
def err_main_surplus_args : Error<"too many parameters (%0) for 'main': "
|
||||
"must be 0, 2, or 3">;
|
||||
|
@ -550,7 +550,8 @@ struct CheckFallThroughDiagnostics {
|
||||
unsigned FunKind; // TODO: use diag::FalloffFunctionKind
|
||||
SourceLocation FuncLoc;
|
||||
|
||||
static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
|
||||
static CheckFallThroughDiagnostics MakeForFunction(Sema &S,
|
||||
const Decl *Func) {
|
||||
CheckFallThroughDiagnostics D;
|
||||
D.FuncLoc = Func->getLocation();
|
||||
D.diag_FallThrough_HasNoReturn = diag::warn_noreturn_has_return_expr;
|
||||
@ -564,8 +565,13 @@ struct CheckFallThroughDiagnostics {
|
||||
|
||||
// Don't suggest that template instantiations be marked "noreturn"
|
||||
bool isTemplateInstantiation = false;
|
||||
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
|
||||
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) {
|
||||
isTemplateInstantiation = Function->isTemplateInstantiation();
|
||||
if (!S.getLangOpts().CPlusPlus && !S.getLangOpts().C99 &&
|
||||
Function->isMain()) {
|
||||
D.diag_FallThrough_ReturnsNonVoid = diag::ext_main_no_return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVirtualMethod && !isTemplateInstantiation)
|
||||
D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function;
|
||||
@ -2737,15 +2743,14 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
|
||||
// Warning: check missing 'return'
|
||||
if (P.enableCheckFallThrough) {
|
||||
const CheckFallThroughDiagnostics &CD =
|
||||
(isa<BlockDecl>(D)
|
||||
? CheckFallThroughDiagnostics::MakeForBlock()
|
||||
: (isa<CXXMethodDecl>(D) &&
|
||||
cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
|
||||
cast<CXXMethodDecl>(D)->getParent()->isLambda())
|
||||
? CheckFallThroughDiagnostics::MakeForLambda()
|
||||
: (fscope->isCoroutine()
|
||||
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
|
||||
: CheckFallThroughDiagnostics::MakeForFunction(D)));
|
||||
(isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
|
||||
: (isa<CXXMethodDecl>(D) &&
|
||||
cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
|
||||
cast<CXXMethodDecl>(D)->getParent()->isLambda())
|
||||
? CheckFallThroughDiagnostics::MakeForLambda()
|
||||
: (fscope->isCoroutine()
|
||||
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
|
||||
: CheckFallThroughDiagnostics::MakeForFunction(S, D)));
|
||||
CheckFallThroughForBody(S, D, Body, BlockType, CD, AC);
|
||||
}
|
||||
|
||||
|
@ -16232,7 +16232,12 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
||||
|
||||
// If the function implicitly returns zero (like 'main') or is naked,
|
||||
// don't complain about missing return statements.
|
||||
if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
|
||||
// Clang implicitly returns 0 in C89 mode, but that's considered an
|
||||
// extension. The check is necessary to ensure the expected extension
|
||||
// warning is emitted in C89 mode.
|
||||
if ((FD->hasImplicitReturnZero() &&
|
||||
(getLangOpts().CPlusPlus || getLangOpts().C99 || !FD->isMain())) ||
|
||||
FD->hasAttr<NakedAttr>())
|
||||
WP.disableCheckFallThrough();
|
||||
|
||||
// MSVC permits the use of pure specifier (=0) on function definition,
|
||||
|
10
clang/test/Sema/main-no-return-c89-1.c
Normal file
10
clang/test/Sema/main-no-return-c89-1.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-strict-prototypes -pedantic %s
|
||||
* RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-strict-prototypes -Wmain-return-type %s
|
||||
* RUN: %clang_cc1 -std=c89 -fsyntax-only -verify=implicit-main-return -Wno-strict-prototypes -pedantic -Wno-main-return-type %s
|
||||
*/
|
||||
|
||||
/* implicit-main-return-no-diagnostics */
|
||||
|
||||
int main() {
|
||||
|
||||
} /* expected-warning {{implicit '0' return value from 'main' is a C99 extension}} */
|
11
clang/test/Sema/main-no-return-c89-2.c
Normal file
11
clang/test/Sema/main-no-return-c89-2.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-strict-prototypes -Wmain-return-type %s
|
||||
*/
|
||||
|
||||
/* expected-no-diagnostics */
|
||||
|
||||
void exit(int);
|
||||
|
||||
int main() {
|
||||
if (1)
|
||||
exit(1);
|
||||
}
|
8
clang/test/Sema/main-no-return-c89-3.c
Normal file
8
clang/test/Sema/main-no-return-c89-3.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-strict-prototypes -Wmain-return-type %s
|
||||
*/
|
||||
|
||||
/* expected-no-diagnostics */
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user