From: John McCall Date: Tue, 14 Feb 2012 19:50:52 +0000 (+0000) Subject: Warn about non-int main() results in GNU C mode instead of erroring. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=75d8ba38965998a07a057c6d1d72359d2cc62c09;p=clang Warn about non-int main() results in GNU C mode instead of erroring. Based on a patch by Vasiliy Korchagin! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150500 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 5d07e5c072..d295683ab7 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -104,6 +104,7 @@ def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args", [CXX98CompatLocalTypeTemplateArgs]>; def MalformedWarningCheck : DiagGroup<"malformed-warning-check">; def Main : DiagGroup<"main">; +def MainReturnType : DiagGroup<"main-return-type">; def MissingBraces : DiagGroup<"missing-braces">; def MissingDeclarations: DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 513b44e7e9..ba7e63ab80 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -346,6 +346,8 @@ def err_constexpr_main : Error< "'main' is not allowed to be declared constexpr">; def err_main_template_decl : Error<"'main' 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; def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " "must be 0, 2, or 3">; def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index de9feccaf3..304304b776 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5794,9 +5794,23 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type"); - const FunctionType* FT = T->getAs(); - - if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + const FunctionType* FT = T->castAs(); + + // All the standards say that main() should should return 'int'. + if (Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + // In C and C++, main magically returns 0 if you fall off the end; + // set the flag which tells us that. + // This is C++ [basic.start.main]p5 and C99 5.1.2.2.3. + FD->setHasImplicitReturnZero(true); + + // In C with GNU extensions we allow main() to have non-integer return + // type, but we should warn about the extension, and we disable the + // implicit-return-zero rule. + } else if (getLangOptions().GNUMode && !getLangOptions().CPlusPlus) { + Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint); + + // Otherwise, this is just a flat-out error. + } else { Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); FD->setInvalidDecl(true); } @@ -7259,16 +7273,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); - if (FD->isMain()) { - // C and C++ allow for main to automagically return 0. - // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3. - FD->setHasImplicitReturnZero(true); - WP.disableCheckFallThrough(); - } else if (FD->hasAttr()) { - // If the function is marked 'naked', don't complain about missing return - // statements. + + // If the function implicitly returns zero (like 'main') or is naked, + // don't complain about missing return statements. + if (FD->hasImplicitReturnZero() || FD->hasAttr()) WP.disableCheckFallThrough(); - } // MSVC permits the use of pure specifier (=0) on function definition, // defined at class scope, warn about this non standard construct. diff --git a/test/Sema/c89.c b/test/Sema/c89.c index 2a791b3c48..ac8c6e0b7b 100644 --- a/test/Sema/c89.c +++ b/test/Sema/c89.c @@ -89,3 +89,5 @@ extern int printf(__const char *__restrict __format, ...); void test16() { printg("Hello, world!\n"); /* expected-warning {{implicit declaration of function 'printg'}} */ } + +void main() {} /* expected-error {{'main' must return 'int'}} */ diff --git a/test/Sema/gnu89.c b/test/Sema/gnu89.c index fc21dcd5cd..189e6b0097 100644 --- a/test/Sema/gnu89.c +++ b/test/Sema/gnu89.c @@ -1,3 +1,5 @@ // RUN: %clang_cc1 %s -std=gnu89 -pedantic -fsyntax-only -verify int f(int restrict); + +void main() {} // expected-warning {{return type of 'main' is not 'int'}}