From: David Blaikie Date: Thu, 8 Sep 2011 06:33:04 +0000 (+0000) Subject: Adding FixIts to static/inline main declaration diagnostics. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=14068e83f30864ed278fa43c5954404b47e99e7d;p=clang Adding FixIts to static/inline main declaration diagnostics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139282 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 933632392f..b6aa33f448 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -289,11 +289,10 @@ def note_strlcpycat_wrong_size : Note< /// 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 warn_static_main : Warning<"'main' should not be declared static">, InGroup
; -def err_unusual_main_decl : Error<"'main' is not allowed to be declared " - "%select{static|inline|static or inline}0">; +def err_static_main : Error<"'main' is not allowed to be declared static">; +def err_inline_main : Error<"'main' is not allowed to be declared inline">; def err_main_template_decl : Error<"'main' cannot be a template">; def err_main_returns_nonint : Error<"'main' must return 'int'">; def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index cfc267c1cf..fce56f0621 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1020,7 +1020,7 @@ public: FunctionDecl *NewFD, LookupResult &Previous, bool IsExplicitSpecialization, bool &Redeclaration); - void CheckMain(FunctionDecl *FD); + void CheckMain(FunctionDecl *FD, const DeclSpec &D); Decl *ActOnParamDeclarator(Scope *S, Declarator &D); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9938954fe1..f4898a1dd8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4782,8 +4782,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!getLangOptions().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; - CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, - Redeclaration); + if (!NewFD->isInvalidDecl()) { + if (NewFD->getResultType()->isVariablyModifiedType()) { + // Functions returning a variably modified type violate C99 6.7.5.2p2 + // because all functions have linkage. + Diag(NewFD->getLocation(), diag::err_vm_func_decl); + NewFD->setInvalidDecl(); + } else { + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, + Redeclaration); + } + } assert((NewFD->isInvalidDecl() || !Redeclaration || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); @@ -4889,9 +4900,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Perform semantic checking on the function declaration. - if (!isDependentClassScopeExplicitSpecialization) - CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, - Redeclaration); + if (!isDependentClassScopeExplicitSpecialization) { + if (NewFD->isInvalidDecl()) { + // If this is a class member, mark the class invalid immediately. + // This avoids some consistency errors later. + if (CXXMethodDecl* methodDecl = dyn_cast(NewFD)) + methodDecl->getParent()->setInvalidDecl(); + } else { + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, + Redeclaration); + } + } assert((NewFD->isInvalidDecl() || !Redeclaration || Previous.getResultKind() != LookupResult::FoundOverloaded) && @@ -5101,25 +5122,8 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsExplicitSpecialization, bool &Redeclaration) { - // If NewFD is already known erroneous, don't do any of this checking. - if (NewFD->isInvalidDecl()) { - // If this is a class member, mark the class invalid immediately. - // This avoids some consistency errors later. - if (isa(NewFD)) - cast(NewFD)->getParent()->setInvalidDecl(); - - return; - } - - if (NewFD->getResultType()->isVariablyModifiedType()) { - // Functions returning a variably modified type violate C99 6.7.5.2p2 - // because all functions have linkage. - Diag(NewFD->getLocation(), diag::err_vm_func_decl); - return NewFD->setInvalidDecl(); - } - - if (NewFD->isMain()) - CheckMain(NewFD); + assert(!NewFD->getResultType()->isVariablyModifiedType() + && "Variably modified return types are not handled here"); // Check for a previous declaration of this name. if (Previous.empty() && NewFD->isExternC()) { @@ -5292,22 +5296,19 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } -void Sema::CheckMain(FunctionDecl* FD) { +void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { // 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->isInlineSpecified(); - bool isStatic = FD->getStorageClass() == SC_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; - } + if (FD->getStorageClass() == SC_Static) + Diag(DS.getStorageClassSpecLoc(), getLangOptions().CPlusPlus + ? diag::err_static_main : diag::warn_static_main) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + if (FD->isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::err_inline_main) + << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type");