From 0d779704f90b773e2c079447ac0e2ee784b56423 Mon Sep 17 00:00:00 2001 From: Richard Smith <richard-llvm@metafoo.co.uk> Date: Wed, 22 Jan 2014 01:43:19 +0000 Subject: [PATCH] Enforce restrictions that 'main' is not allowed to be deleted, or to be used by the program, in C++. (We allow the latter as an extension, since we've always permitted it, and GCC does the same, and our supported C++ ABIs don't do anything special in main.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199782 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ lib/Sema/SemaDecl.cpp | 7 +++++-- lib/Sema/SemaDeclCXX.cpp | 5 +++++ lib/Sema/SemaExpr.cpp | 7 ++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ac5b406b801..e9780430e64 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -425,6 +425,7 @@ def ext_noreturn_main : ExtWarn< def note_main_remove_noreturn : Note<"remove '_Noreturn'">; def err_constexpr_main : Error< "'main' is not allowed to be declared constexpr">; +def err_deleted_main : Error<"'main' is not allowed to be deleted">; def err_mainlike_template_decl : Error<"%0 cannot be a template">; def err_main_returns_nonint : Error<"'main' must return 'int'">; def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">, @@ -437,6 +438,8 @@ def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "parameter of 'main' (%select{argument count|argument array|environment|" "platform-specific data}0) must be of type %1">; +def ext_main_used : Extension< + "ISO C++ does not allow 'main' to be used by a program">, InGroup<Main>; /// parser diagnostics def ext_no_declarators : ExtWarn<"declaration does not declare anything">, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c08d87d59a8..9dac4d53024 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6809,6 +6809,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // If a function is defined as defaulted or deleted, mark it as such now. + // FIXME: Does this ever happen? ActOnStartOfFunctionDef forces the function + // definition kind to FDK_Definition. switch (D.getFunctionDefinitionKind()) { case FDK_Declaration: case FDK_Definition: @@ -7670,8 +7672,9 @@ static SourceRange getResultSourceRange(const FunctionDecl *FD) { } void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { - // C++11 [basic.start.main]p3: A program that declares main to be inline, - // static or constexpr is ill-formed. + // C++11 [basic.start.main]p3: + // A program that [...] declares main to be inline, static or + // constexpr is ill-formed. // C11 6.7.4p4: In a hosted environment, no function specifier(s) shall // appear in a declaration of main. // static main is not an error under C99, but we should warn about it. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 39d71e20163..76b9d669d42 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -11984,6 +11984,11 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { } } + // C++11 [basic.start.main]p3: + // A program that defines main as deleted [...] is ill-formed. + if (Fn->isMain()) + Diag(DelLoc, diag::err_deleted_main); + Fn->setDeletedAsWritten(); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3640c5ad24b..ff54b6b24e4 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -264,13 +264,18 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second; for (unsigned I = 0, N = Suppressed.size(); I != N; ++I) Diag(Suppressed[I].first, Suppressed[I].second); - + // Clear out the list of suppressed diagnostics, so that we don't emit // them again for this specialization. However, we don't obsolete this // entry from the table, because we want to avoid ever emitting these // diagnostics again. Suppressed.clear(); } + + // C++ [basic.start.main]p3: + // The function 'main' shall not be used within a program. + if (cast<FunctionDecl>(D)->isMain()) + Diag(Loc, diag::ext_main_used); } // See if this is an auto-typed variable whose initializer we are parsing. -- GitLab