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 5d07e5c..d295683 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -104,6 +104,7 @@
[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 513b44e..ba7e63a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -346,6 +346,8 @@
"'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 de9fecc..304304b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5794,9 +5794,23 @@
QualType T = FD->getType();
assert(T->isFunctionType() && "function decl is not of function type");
- const FunctionType* FT = T->getAs<FunctionType>();
+ const FunctionType* FT = T->castAs<FunctionType>();
- if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+ // 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 @@
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);
+
+ // 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();
- } else if (FD->hasAttr<NakedAttr>()) {
- // If the function is marked 'naked', don't complain about missing return
- // statements.
- 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 2a791b3..ac8c6e0 100644
--- a/test/Sema/c89.c
+++ b/test/Sema/c89.c
@@ -89,3 +89,5 @@
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 fc21dcd..189e6b0 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'}}