davide updated this revision to Diff 31932.
davide added a comment.
- Refactored check
- Added test for -ffreestanding in C
- Changed the diagnostic emitted
Also, thanks for your time and guidance.
http://reviews.llvm.org/D11658
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/CXX/basic/basic.start/basic.start.main/p3.cpp
test/Sema/warn-extern-main.c
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
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
+templateclass T constexpr T main;
+
+#elif TEST6
+extern templateclass 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 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: 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_castNamedDecl(Previous.getRepresentativeDecl()), NewVD,
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