forked from OSchip/llvm-project
Semantic checking for main().
Fix some invalid main() methods in the test suite that were nicely exposed by the new checks. llvm-svn: 77047
This commit is contained in:
parent
732d15b9b9
commit
02dee0a46a
|
@ -126,6 +126,19 @@ def err_builtin_definition : Error<"definition of builtin function %0">;
|
|||
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<
|
||||
|
|
|
@ -2767,7 +2767,85 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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[]) {
|
||||
}
|
|
@ -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[]) {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
int main() {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
static int main() { // expected-error {{'main' is not allowed to be declared static}}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
inline int main() { // expected-error {{'main' is not allowed to be declared inline}}
|
||||
}
|
|
@ -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
|
||||
) {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
int main(int argc, const char* const* argv) {
|
||||
}
|
|
@ -38,7 +38,7 @@ volatile extv4 vVE;
|
|||
|
||||
volatile struct {int x;} aggFct(void);
|
||||
|
||||
void main() {
|
||||
int main() {
|
||||
int i;
|
||||
|
||||
// load
|
||||
|
|
|
@ -22,7 +22,7 @@ void test() {
|
|||
^(int x, ...){return 5;}(arg, arg); // Explicit varargs, ok.
|
||||
}
|
||||
|
||||
int main(int argc) {
|
||||
int main(int argc, char** argv) {
|
||||
^(int argCount) {
|
||||
argCount = 3;
|
||||
}(argc);
|
||||
|
|
|
@ -26,7 +26,7 @@ id getProperty(id self) {
|
|||
@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)
|
||||
|
|
Loading…
Reference in New Issue