Author: majnemer Date: Mon Sep 16 17:44:20 2013 New Revision: 190818 URL: http://llvm.org/viewvc/llvm-project?rev=190818&view=rev Log: [-cxx-abi microsoft] Correctly identify Win32 entry points
Summary: This fixes several issues with the original implementation: - Win32 entry points cannot be in namespaces - A Win32 entry point cannot be a function template, diagnose if we it. - Win32 entry points cannot be overloaded. - Win32 entry points implicitly return, similar to main. Reviewers: rnk, rsmith, whunt, timurrrr Reviewed By: rnk CC: cfe-commits, nrieck Differential Revision: http://llvm-reviews.chandlerc.com/D1683 Added: cfe/trunk/test/SemaCXX/ms-overload-entry-point.cpp Modified: cfe/trunk/include/clang/AST/Decl.h cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/AST/MicrosoftMangle.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaOverload.cpp Modified: cfe/trunk/include/clang/AST/Decl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Decl.h (original) +++ cfe/trunk/include/clang/AST/Decl.h Mon Sep 16 17:44:20 2013 @@ -1735,6 +1735,10 @@ public: /// entry point into an executable program. bool isMain() const; + /// \brief Determines whether this function is a MSVCRT user defined entry + /// point. + bool isMSVCRTEntryPoint() const; + /// \brief Determines whether this operator new or delete is one /// of the reserved global placement operators: /// void *operator new(size_t, void *); Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Sep 16 17:44:20 2013 @@ -419,7 +419,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_main_template_decl : Error<"'main' cannot be a template">; +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'">, InGroup<MainReturnType>; Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Sep 16 17:44:20 2013 @@ -1495,6 +1495,7 @@ public: FunctionDecl *NewFD, LookupResult &Previous, bool IsExplicitSpecialization); void CheckMain(FunctionDecl *FD, const DeclSpec &D); + void CheckMSVCRTEntryPoint(FunctionDecl *FD); Decl *ActOnParamDeclarator(Scope *S, Declarator &D); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Mon Sep 16 17:44:20 2013 @@ -2204,6 +2204,33 @@ bool FunctionDecl::isMain() const { isNamed(this, "main"); } +bool FunctionDecl::isMSVCRTEntryPoint() const { + const TranslationUnitDecl *TUnit = + dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); + if (!TUnit) + return false; + + // Even though we aren't really targeting MSVCRT if we are freestanding, + // semantic analysis for these functions remains the same. + + // MSVCRT entry points only exist on MSVCRT targets. + if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT()) + return false; + + // Nameless functions like constructors cannot be entry points. + if (!getIdentifier()) + return false; + + return llvm::StringSwitch<bool>(getName()) + .Cases("main", // an ANSI console app + "wmain", // a Unicode console App + "WinMain", // an ANSI GUI app + "wWinMain", // a Unicode GUI app + "DllMain", // a DLL + true) + .Default(false); +} + bool FunctionDecl::isReservedGlobalPlacementOperator() const { assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName); assert(getDeclName().getCXXOverloadedOperator() == OO_New || Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original) +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Mon Sep 16 17:44:20 2013 @@ -24,7 +24,6 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -71,29 +70,6 @@ static const FunctionDecl *getStructor(c return fn; } -// The ABI expects that we would never mangle "typical" user-defined entry -// points regardless of visibility or freestanding-ness. -// -// N.B. This is distinct from asking about "main". "main" has a lot of special -// rules associated with it in the standard while these user-defined entry -// points are outside of the purview of the standard. For example, there can be -// only one definition for "main" in a standards compliant program; however -// nothing forbids the existence of wmain and WinMain in the same translation -// unit. -static bool isUserDefinedEntryPoint(const FunctionDecl *FD) { - if (!FD->getIdentifier()) - return false; - - return llvm::StringSwitch<bool>(FD->getName()) - .Cases("main", // An ANSI console app - "wmain", // A Unicode console App - "WinMain", // An ANSI GUI app - "wWinMain", // A Unicode GUI app - "DllMain", // A DLL - true) - .Default(false); -} - /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the /// Microsoft Visual C++ ABI. class MicrosoftCXXNameMangler { @@ -254,7 +230,16 @@ bool MicrosoftMangleContext::shouldMangl if (FD->hasAttr<OverloadableAttr>()) return true; - if (isUserDefinedEntryPoint(FD)) + // The ABI expects that we would never mangle "typical" user-defined entry + // points regardless of visibility or freestanding-ness. + // + // N.B. This is distinct from asking about "main". "main" has a lot of + // special rules associated with it in the standard while these + // user-defined entry points are outside of the purview of the standard. + // For example, there can be only one definition for "main" in a standards + // compliant program; however nothing forbids the existence of wmain and + // WinMain in the same translation unit. + if (FD->isMSVCRTEntryPoint()) return false; // C++ functions and those whose names are not a simple identifier need Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Sep 16 17:44:20 2013 @@ -6881,6 +6881,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, if (!NewFD->isInvalidDecl() && NewFD->isMain()) CheckMain(NewFD, D.getDeclSpec()); + if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) + CheckMSVCRTEntryPoint(NewFD); + if (!NewFD->isInvalidDecl()) D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); @@ -7000,6 +7003,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, if (!NewFD->isInvalidDecl() && NewFD->isMain()) CheckMain(NewFD, D.getDeclSpec()); + if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) + CheckMSVCRTEntryPoint(NewFD); + if (NewFD->isInvalidDecl()) { // If this is a class member, mark the class invalid immediately. // This avoids some consistency errors later. @@ -7670,7 +7676,27 @@ void Sema::CheckMain(FunctionDecl* FD, c } if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { - Diag(FD->getLocation(), diag::err_main_template_decl); + Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName(); + FD->setInvalidDecl(); + } +} + +void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) { + QualType T = FD->getType(); + assert(T->isFunctionType() && "function decl is not of function type"); + const FunctionType *FT = T->castAs<FunctionType>(); + + // Set an implicit return of 'zero' if the function can return some integral, + // enumeration, pointer or nullptr type. + if (FT->getResultType()->isIntegralOrEnumerationType() || + FT->getResultType()->isAnyPointerType() || + FT->getResultType()->isNullPtrType()) + // DllMain is exempt because a return value of zero means it failed. + if (FD->getName() != "DllMain") + FD->setHasImplicitReturnZero(true); + + if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { + Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName(); FD->setInvalidDecl(); } } Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=190818&r1=190817&r2=190818&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Sep 16 17:44:20 2013 @@ -21,6 +21,7 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -979,6 +980,10 @@ bool Sema::IsOverload(FunctionDecl *New, if (New->isMain()) return false; + // MSVCRT user defined entry points cannot be overloaded. + if (New->isMSVCRTEntryPoint()) + return false; + FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); Added: cfe/trunk/test/SemaCXX/ms-overload-entry-point.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-overload-entry-point.cpp?rev=190818&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/ms-overload-entry-point.cpp (added) +++ cfe/trunk/test/SemaCXX/ms-overload-entry-point.cpp Mon Sep 16 17:44:20 2013 @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -triple i386-pc-win32 %s + +template <typename T> +int wmain() { // expected-error{{'wmain' cannot be a template}} + return 0; +} + +namespace { +int WinMain(void) { return 0; } +int WinMain(int) { return 0; } +} + +void wWinMain(void) {} // expected-note{{previous definition is here}} +void wWinMain(int) {} // expected-error{{conflicting types for 'wWinMain'}} + +int foo() { + wmain<void>(); // expected-error{{no matching function for call to 'wmain'}} + wmain<int>(); // expected-error{{no matching function for call to 'wmain'}} + WinMain(); + return 0; +} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
