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 | 5ed3caf2e3640cf5e16e901094f7c3c5cee20ea0 (patch) | |
| tree | 6e5fa93368f4c709c1136a96ca3f99db9d57a479 | |
| parent | d2a9075de0a21548b9f01d24ed309bc5cb26f99f (diff) | |
| download | bcm5719-llvm-5ed3caf2e3640cf5e16e901094f7c3c5cee20ea0.tar.gz bcm5719-llvm-5ed3caf2e3640cf5e16e901094f7c3c5cee20ea0.zip | |
Warn about non-int main() results in GNU C mode instead of erroring.
Based on a patch by Vasiliy Korchagin!
llvm-svn: 150500
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 1 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 | ||||
| -rw-r--r-- | clang/test/Sema/c89.c | 2 | ||||
| -rw-r--r-- | clang/test/Sema/gnu89.c | 2 |
5 files changed, 28 insertions, 12 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 5d07e5c072f..d295683ab70 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/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/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 513b44e7e92..ba7e63ab803 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index de9feccaf33..304304b776c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/test/Sema/c89.c b/clang/test/Sema/c89.c index 2a791b3c486..ac8c6e0b7b7 100644 --- a/clang/test/Sema/c89.c +++ b/clang/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/clang/test/Sema/gnu89.c b/clang/test/Sema/gnu89.c index fc21dcd5cd4..189e6b0097a 100644 --- a/clang/test/Sema/gnu89.c +++ b/clang/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'}} |

