Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -510,6 +510,9 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "parameter of 'main' (%select{argument count|argument array|environment|" "platform-specific data}0) must be of type %1">; +def err_main_global_variable : Error<"main can't be declared as global variable">; +def warn_main_redefined : Warning<"external-linkage variable named 'main' has " + "undefined behavior">, InGroup
; def ext_main_used : Extension< "ISO C++ does not allow 'main' to be used by a program">, InGroup
; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -6111,6 +6111,22 @@ } } + // Special handling of variable named 'main'. + if (Name.isIdentifier() && Name.getAsIdentifierInfo()->isStr("main") && + NewVD->getDeclContext()->getRedeclContext()->isTranslationUnit() && + !getLangOpts().Freestanding && !NewVD->getDescribedVarTemplate()) { + + // C++ [basic.start.main]p3 + // A program that declares a variable main at global scope is ill-formed. + if (getLangOpts().CPlusPlus) + Diag(D.getLocStart(), diag::err_main_global_variable); + + // In C, and external-linkage variable named main results in undefined + // behavior. + else if (NewVD->hasExternalFormalLinkage()) + Diag(D.getLocStart(), diag::warn_main_redefined); + } + if (D.isRedeclaration() && !Previous.empty()) { checkDLLAttributeRedeclaration( *this, dyn_cast(Previous.getRepresentativeDecl()), NewVD, Index: test/CXX/basic/basic.start/basic.start.main/p3.cpp =================================================================== --- test/CXX/basic/basic.start/basic.start.main/p3.cpp +++ test/CXX/basic/basic.start/basic.start.main/p3.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST1 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST2 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST3 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST4 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14 -DTEST5 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14 -DTEST6 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST7 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST8 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST9 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST10 -ffreestanding + +#if TEST1 +int main; // expected-error{{main can't be declared as global variable}} + +#elif TEST2 +// expected-no-diagnostics +int f () { + int main; + return main; +} + +#elif TEST3 +// expected-no-diagnostics +void x(int main) {}; +int y(int main); + +#elif TEST4 +// expected-no-diagnostics +class A { + static int main; +}; + +#elif TEST5 +// expected-no-diagnostics +template constexpr T main; + +#elif TEST6 +extern template constexpr T main; //expected-error{{expected unqualified-id}} + +#elif TEST7 +// expected-no-diagnostics +namespace foo { + int main; +} + +#elif TEST8 +void z(void) +{ + extern int main; // expected-error{{main can't be declared as global variable}} +} + +#elif TEST9 +// expected-no-diagnostics +int q(void) +{ + static int main; + return main; +} + +#elif TEST10 +// expected-no-diagnostics +int main; + +#else +#error Unknown Test +#endif Index: test/Sema/warn-extern-main.c =================================================================== --- test/Sema/warn-extern-main.c +++ test/Sema/warn-extern-main.c @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST1 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST2 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST3 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST4 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST5 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST6 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST7 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST8 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DTEST9 -ffreestanding + +#if TEST1 +int main; // expected-warning{{external-linkage variable named 'main' has undefined behavior}} + +#elif TEST2 +extern int main; // expected-warning{{external-linkage variable named 'main' has undefined behavior}} + +#elif TEST3 +// expected-no-diagnostics +void x() { + static int main; +} + +#elif TEST4 +void x() { + extern int main; // expected-warning{{external-linkage variable named 'main' has undefined behavior}} +} + +#elif TEST5 +// expected-no-diagnostics +void x() { + int main; +} + +#elif TEST6 +// expected-no-diagnostics +static int main; + +#elif TEST7 +// expected-no-diagnostics +void x() { + auto int main; +} + +#elif TEST8 +// expected-no-diagnostics +void x() { + register int main; +} + +#elif TEST9 +// expected-no-diagnostics +int main; + +#else +#error Unknown Test +#endif