From 70fc29ca86f0f852ed0e3d007cff7b45bb396e7c Mon Sep 17 00:00:00 2001 From: Alp Toker Date: Wed, 2 Jul 2014 07:07:20 +0000 Subject: [PATCH] Don't accept qualified 'int' main return types in C++ or standard C mode C++ [basic.start.main]p1: "It shall have a return type of type int" ISO C is also clear about this, so only accept 'int' with qualifiers in GNUMode C. llvm-svn: 212171 --- clang/lib/Sema/SemaDecl.cpp | 49 ++++++++++--------- .../basic/basic.start/basic.start.main/p2.cpp | 2 + clang/test/Sema/c89.c | 2 + 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 849926327d08..791b4daf01ea 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7878,32 +7878,37 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { assert(T->isFunctionType() && "function decl is not of function type"); const FunctionType* FT = T->castAs(); - // All the standards say that main() should should return 'int'. - if (Context.hasSameUnqualifiedType(FT->getReturnType(), Context.IntTy)) { + if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { + // 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. + + // GCC in C mode accepts qualified 'int'. + if (Context.hasSameUnqualifiedType(FT->getReturnType(), Context.IntTy)) + FD->setHasImplicitReturnZero(true); + else { + Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint); + SourceRange RTRange = FD->getReturnTypeSourceRange(); + if (RTRange.isValid()) + Diag(RTRange.getBegin(), diag::note_main_change_return_type) + << FixItHint::CreateReplacement(RTRange, "int"); + } + } else { // 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 (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { - Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint); - - SourceRange RTRange = FD->getReturnTypeSourceRange(); - if (RTRange.isValid()) - Diag(RTRange.getBegin(), diag::note_main_change_return_type) - << FixItHint::CreateReplacement(RTRange, "int"); - - // Otherwise, this is just a flat-out error. - } else { - SourceRange RTRange = FD->getReturnTypeSourceRange(); - Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint) - << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "int") - : FixItHint()); - - FD->setInvalidDecl(true); + // All the standards say that main() should return 'int'. + if (Context.hasSameType(FT->getReturnType(), Context.IntTy)) + FD->setHasImplicitReturnZero(true); + else { + // Otherwise, this is just a flat-out error. + SourceRange RTRange = FD->getReturnTypeSourceRange(); + Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint) + << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "int") + : FixItHint()); + FD->setInvalidDecl(true); + } } // Treat protoless main() as nullary. diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2.cpp index 5c7d60c1df4c..42e87e5431f2 100644 --- a/clang/test/CXX/basic/basic.start/basic.start.main/p2.cpp +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2.cpp @@ -62,6 +62,8 @@ main( // expected-error {{first parameter of 'main' (argument count) must be of ) { } +const int main(); // expected-error {{'main' must return 'int'}} + #elif TEST7 // expected-no-diagnostics diff --git a/clang/test/Sema/c89.c b/clang/test/Sema/c89.c index b746d383f306..c9e81f1c41ca 100644 --- a/clang/test/Sema/c89.c +++ b/clang/test/Sema/c89.c @@ -111,6 +111,8 @@ const array_of_pointer_to_CI mine3; void main() {} /* expected-error {{'main' must return 'int'}} */ +const int main() {} /* expected-error {{'main' must return 'int'}} */ + long long ll1 = /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */ -42LL; /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */ unsigned long long ull1 = /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */