Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,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)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@ 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<"non-void 'main' function does not return a value">,
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">;
Expand Down
27 changes: 16 additions & 11 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16232,7 +16232,9 @@ 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>())
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,
Expand Down
6 changes: 6 additions & 0 deletions clang/test/Sema/main-no-return-c89.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -pedantic -Wno-strict-prototypes %s
*/

int main() {

} /* expected-warning {{non-void 'main' function does not return a value}} */