mirror of https://github.com/microsoft/clang.git
[Sema] main can't be declared as global variable, in C++.
So, we now reject that. We also warn for any external-linkage global variable named main in C, because it results in undefined behavior. PR: 24309 Differential Revision: http://reviews.llvm.org/D11658 Reviewed by: rsmith git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@245051 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d2bb239313
commit
93fc20d91c
|
@ -510,6 +510,10 @@ def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">,
|
||||||
def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
|
def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
|
||||||
"parameter of 'main' (%select{argument count|argument array|environment|"
|
"parameter of 'main' (%select{argument count|argument array|environment|"
|
||||||
"platform-specific data}0) must be of type %1">;
|
"platform-specific data}0) must be of type %1">;
|
||||||
|
def err_main_global_variable :
|
||||||
|
Error<"main cannot be declared as global variable">;
|
||||||
|
def warn_main_redefined : Warning<"variable named 'main' with external linkage "
|
||||||
|
"has undefined behavior">, InGroup<Main>;
|
||||||
def ext_main_used : Extension<
|
def ext_main_used : Extension<
|
||||||
"ISO C++ does not allow 'main' to be used by a program">, InGroup<Main>;
|
"ISO C++ does not allow 'main' to be used by a program">, InGroup<Main>;
|
||||||
|
|
||||||
|
|
|
@ -6111,6 +6111,22 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()) {
|
if (D.isRedeclaration() && !Previous.empty()) {
|
||||||
checkDLLAttributeRedeclaration(
|
checkDLLAttributeRedeclaration(
|
||||||
*this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
|
*this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
|
||||||
|
|
|
@ -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 cannot 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<class T> constexpr T main;
|
||||||
|
|
||||||
|
#elif TEST6
|
||||||
|
extern template<class T> 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 cannot 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
|
|
@ -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{{variable named 'main' with external linkage has undefined behavior}}
|
||||||
|
|
||||||
|
#elif TEST2
|
||||||
|
extern int main; // expected-warning{{variable named 'main' with external linkage has undefined behavior}}
|
||||||
|
|
||||||
|
#elif TEST3
|
||||||
|
// expected-no-diagnostics
|
||||||
|
void x() {
|
||||||
|
static int main;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif TEST4
|
||||||
|
void x() {
|
||||||
|
extern int main; // expected-warning{{variable named 'main' with external linkage 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
|
Loading…
Reference in New Issue