From: Alp Toker Date: Wed, 2 Jul 2014 07:07:20 +0000 (+0000) Subject: Don't accept qualified 'int' main return types in C++ or standard C mode X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c533089456fdae3a0dbdd765f959078f05aa4629;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212171 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 849926327d..791b4daf01 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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/test/CXX/basic/basic.start/basic.start.main/p2.cpp b/test/CXX/basic/basic.start/basic.start.main/p2.cpp index 5c7d60c1df..42e87e5431 100644 --- a/test/CXX/basic/basic.start/basic.start.main/p2.cpp +++ b/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/test/Sema/c89.c b/test/Sema/c89.c index b746d383f3..c9e81f1c41 100644 --- a/test/Sema/c89.c +++ b/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}} */