[cfe-commits] r77047 - in /cfe/trunk: include/clang/Basic/ lib/Sema/ test/CXX/basic/basic.start/basic.start.main/ test/CodeGen/ test/Sema/ test/SemaObjC/
John McCall
rjmccall at apple.com
Fri Jul 24 21:36:53 PDT 2009
Author: rjmccall
Date: Fri Jul 24 23:36:53 2009
New Revision: 77047
URL: http://llvm.org/viewvc/llvm-project?rev=77047&view=rev
Log:
Semantic checking for main().
Fix some invalid main() methods in the test suite that were nicely
exposed by the new checks.
Added:
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2a.cpp
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2b.cpp
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2c.cpp
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2d.cpp
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2e.cpp
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2f.cpp
cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2g.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGen/volatile.c
cfe/trunk/test/Sema/block-args.c
cfe/trunk/test/SemaObjC/nsobject-attribute.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=77047&r1=77046&r2=77047&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jul 24 23:36:53 2009
@@ -126,6 +126,19 @@
def err_types_compatible_p_in_cplusplus : Error<
"__builtin_types_compatible_p is not valid in C++">;
+/// main()
+// static/inline main() are not errors in C, just in C++.
+def warn_unusual_main_decl : Warning<"'main' should not be declared "
+ "%select{static|inline|static or inline}0">;
+def err_unusual_main_decl : Error<"'main' is not allowed to be declared "
+ "%select{static|inline|static or inline}0">;
+def err_main_returns_nonint : Error<"'main' must return 'int'">;
+def err_main_surplus_args : Error<"%0 is too many arguments for 'main': "
+ "must be 0, 2, or 3">;
+def warn_main_one_arg : Warning<"one-argument 'main' is usually a mistake">;
+def err_main_arg_wrong : Error<"%select{first|second|third}0 argument of "
+ "'main' should be of type %1">;
+
/// parser diagnostics
def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">;
def err_statically_allocated_object : Error<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=77047&r1=77046&r2=77047&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jul 24 23:36:53 2009
@@ -2767,7 +2767,85 @@
}
void Sema::CheckMain(FunctionDecl* FD) {
- // FIXME: implement.
+ // C++ [basic.start.main]p3: A program that declares main to be inline
+ // or static is ill-formed.
+ // C99 6.7.4p4: In a hosted environment, the inline function specifier
+ // shall not appear in a declaration of main.
+ // static main is not an error under C99, but we should warn about it.
+ bool isInline = FD->isInline();
+ bool isStatic = FD->getStorageClass() == FunctionDecl::Static;
+ if (isInline || isStatic) {
+ unsigned diagID = diag::warn_unusual_main_decl;
+ if (isInline || getLangOptions().CPlusPlus)
+ diagID = diag::err_unusual_main_decl;
+
+ int which = isStatic + (isInline << 1) - 1;
+ Diag(FD->getLocation(), diagID) << which;
+ }
+
+ QualType T = FD->getType();
+ assert(T->isFunctionType() && "function decl is not of function type");
+ const FunctionType* FT = T->getAsFunctionType();
+
+ if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+ // TODO: add a replacement fixit to turn the return type into 'int'.
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+ FD->setInvalidDecl(true);
+ }
+
+ // Treat protoless main() as nullary.
+ if (isa<FunctionNoProtoType>(FT)) return;
+
+ const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
+ unsigned nparams = FTP->getNumArgs();
+ assert(FD->getNumParams() == nparams);
+
+ if (nparams > 3) {
+ Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
+ FD->setInvalidDecl(true);
+ nparams = 3;
+ }
+
+ // FIXME: a lot of the following diagnostics would be improved
+ // if we had some location information about types.
+
+ QualType CharPP =
+ Context.getPointerType(Context.getPointerType(Context.CharTy));
+ QualType Expected[] = { Context.IntTy, CharPP, CharPP };
+
+ for (unsigned i = 0; i < nparams; ++i) {
+ QualType AT = FTP->getArgType(i);
+
+ bool mismatch = true;
+
+ if (Context.hasSameUnqualifiedType(AT, Expected[i]))
+ mismatch = false;
+ else if (Expected[i] == CharPP) {
+ // As an extension, the following forms are okay:
+ // char const **
+ // char const * const *
+ // char * const *
+
+ QualifierSet qs;
+ const PointerType* PT;
+ if ((PT = qs.strip(AT)->getAsPointerType()) &&
+ (PT = qs.strip(PT->getPointeeType())->getAsPointerType()) &&
+ (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) {
+ qs.removeConst();
+ mismatch = !qs.empty();
+ }
+ }
+
+ if (mismatch) {
+ Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i];
+ // TODO: suggest replacing given type with expected type
+ FD->setInvalidDecl(true);
+ }
+ }
+
+ if (nparams == 1 && !FD->isInvalidDecl()) {
+ Diag(FD->getLocation(), diag::warn_main_one_arg);
+ }
}
bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2a.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2a.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2a.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2a.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef int Int;
+typedef char Char;
+typedef Char* Carp;
+
+Int main(Int argc, Carp argv[]) {
+}
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2b.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2b.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2b.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2b.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef int Int;
+typedef char Char;
+typedef Char* Carp;
+
+Int main(Int argc, Carp argv[], Char *env[]) {
+}
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2c.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2c.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2c.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2c.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+int main() {
+}
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2d.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2d.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2d.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2d.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+static int main() { // expected-error {{'main' is not allowed to be declared static}}
+}
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2e.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2e.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2e.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2e.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+inline int main() { // expected-error {{'main' is not allowed to be declared inline}}
+}
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2f.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2f.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2f.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2f.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void // expected-error {{error: 'main' must return 'int'}}
+main( // expected-error {{error: first argument of 'main' should be of type 'int'}}
+ float a
+) {
+}
Added: cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2g.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2g.cpp?rev=77047&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2g.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.start/basic.start.main/p2g.cpp Fri Jul 24 23:36:53 2009
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+int main(int argc, const char* const* argv) {
+}
Modified: cfe/trunk/test/CodeGen/volatile.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/volatile.c?rev=77047&r1=77046&r2=77047&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/volatile.c (original)
+++ cfe/trunk/test/CodeGen/volatile.c Fri Jul 24 23:36:53 2009
@@ -38,7 +38,7 @@
volatile struct {int x;} aggFct(void);
-void main() {
+int main() {
int i;
// load
Modified: cfe/trunk/test/Sema/block-args.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/block-args.c?rev=77047&r1=77046&r2=77047&view=diff
==============================================================================
--- cfe/trunk/test/Sema/block-args.c (original)
+++ cfe/trunk/test/Sema/block-args.c Fri Jul 24 23:36:53 2009
@@ -22,7 +22,7 @@
^(int x, ...){return 5;}(arg, arg); // Explicit varargs, ok.
}
-int main(int argc) {
+int main(int argc, char** argv) {
^(int argCount) {
argCount = 3;
}(argc);
Modified: cfe/trunk/test/SemaObjC/nsobject-attribute.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/nsobject-attribute.m?rev=77047&r1=77046&r2=77047&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/nsobject-attribute.m (original)
+++ cfe/trunk/test/SemaObjC/nsobject-attribute.m Fri Jul 24 23:36:53 2009
@@ -26,7 +26,7 @@
@synthesize x=x;
@end
-int main(char *argc, char *argv[]) {
+int main(int argc, char *argv[]) {
HandTested *to;
to.x = tmp; // setter
if (tmp != to.x)
More information about the cfe-commits
mailing list