diff options
author | John McCall <rjmccall@apple.com> | 2012-02-14 19:50:52 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-02-14 19:50:52 +0000 |
commit | 75d8ba38965998a07a057c6d1d72359d2cc62c09 (patch) | |
tree | ead1209de5aa69b12c84f4f21f4197dfeffab2fc | |
parent | 0a525340ada570897ab34918c98de1cf94ad7770 (diff) |
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
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 33 | ||||
-rw-r--r-- | test/Sema/c89.c | 2 | ||||
-rw-r--r-- | test/Sema/gnu89.c | 2 |
5 files changed, 28 insertions, 12 deletions
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<MainReturnType>; 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<FunctionType>(); - - if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + const FunctionType* FT = T->castAs<FunctionType>(); + + // 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<NakedAttr>()) { - // 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<NakedAttr>()) 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'}} |