From: David Majnemer Date: Tue, 11 Feb 2014 21:05:00 +0000 (+0000) Subject: MS ABI: Add support for the -vm{b,g,s,m,v} flags X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=86c318f4962fb18383c184a380e294e2b5589456;p=platform%2Fupstream%2Fllvm.git MS ABI: Add support for the -vm{b,g,s,m,v} flags These flags control the inheritance model initially used by the translation unit. Differential Revision: http://llvm-reviews.chandlerc.com/D2741 llvm-svn: 201175 --- diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 34dfea2..2fa6850 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -113,6 +113,7 @@ BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __w BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") LANGOPT(CharIsSigned , 1, 1, "signed char") LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") +ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") LANGOPT(ShortEnums , 1, 0, "short enum types") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 7b2b18d..e969161 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -66,6 +66,13 @@ public: SOB_Trapping // -ftrapv }; + enum PragmaMSPointersToMembersKind { + PPTMK_BestCase, + PPTMK_FullGeneralitySingleInheritance, + PPTMK_FullGeneralityMultipleInheritance, + PPTMK_FullGeneralityVirtualInheritance + }; + enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; public: diff --git a/clang/include/clang/Driver/CLCompatOptions.td b/clang/include/clang/Driver/CLCompatOptions.td index fa28a01..ec828b0 100644 --- a/clang/include/clang/Driver/CLCompatOptions.td +++ b/clang/include/clang/Driver/CLCompatOptions.td @@ -96,6 +96,16 @@ def _SLASH_showIncludes : CLFlag<"showIncludes">, Alias; def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">, MetaVarName<"">, Alias; +def _SLASH_vmb : CLFlag<"vmb">, + HelpText<"Use a best-case representation method for member pointers">; +def _SLASH_vmg : CLFlag<"vmg">, + HelpText<"Use a most-general representation for member pointers">; +def _SLASH_vms : CLFlag<"vms">, + HelpText<"Set the default most-general representation to single inheritance">; +def _SLASH_vmm : CLFlag<"vmm">, + HelpText<"Set the default most-general representation to multiple inheritance">; +def _SLASH_vmv : CLFlag<"vmv">, + HelpText<"Set the default most-general representation to virtual inheritance">; def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias; def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias; def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias; @@ -168,7 +178,6 @@ def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">; def _SLASH_RTC : CLIgnoredJoined<"RTC">; def _SLASH_sdl : CLIgnoredFlag<"sdl">; def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">; -def _SLASH_vmg : CLIgnoredFlag<"vmg">; def _SLASH_w : CLIgnoredJoined<"w">; def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">; def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">; @@ -233,10 +242,6 @@ def _SLASH_Qvec_report : CLJoined<"Qvec-report">; def _SLASH_u : CLFlag<"u">; def _SLASH_V : CLFlag<"V">; def _SLASH_vd : CLJoined<"vd">; -def _SLASH_vmb : CLFlag<"vmb">; -def _SLASH_vmm : CLFlag<"vmm">; -def _SLASH_vms : CLFlag<"vms">; -def _SLASH_vmv : CLFlag<"vmv">; def _SLASH_volatile : CLFlag<"volatile">; def _SLASH_WL : CLFlag<"WL">; def _SLASH_Wp64 : CLFlag<"Wp64">; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index de31361..52cd9ef 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -571,6 +571,7 @@ def fmsc_version : Joined<["-"], "fmsc-version=">, Group, Flags<[CC1Opt def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group, HelpText<"Parse templated function definitions at the end of the " "translation unit">, Flags<[CC1Option]>; +def fms_memptr_rep_EQ : Joined<["-"], "fms-memptr-rep=">, Group, Flags<[CC1Option]>; def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">, HelpText<"Specify the module cache path">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 78a19d1..2f72306 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -262,15 +262,9 @@ public: bool MSStructPragmaOn; // True when \#pragma ms_struct on - enum PragmaMSPointersToMembersKind { - PPTMK_BestCase, - PPTMK_FullGeneralitySingleInheritance, - PPTMK_FullGeneralityMultipleInheritance, - PPTMK_FullGeneralityVirtualInheritance - }; - /// \brief Controls member pointer representation format under the MS ABI. - PragmaMSPointersToMembersKind MSPointerToMemberRepresentationMethod; + LangOptions::PragmaMSPointersToMembersKind + MSPointerToMemberRepresentationMethod; /// \brief Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; @@ -6986,8 +6980,9 @@ public: /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma /// pointers_to_members(representation method[, general purpose /// representation]). - void ActOnPragmaMSPointersToMembers(PragmaMSPointersToMembersKind Kind, - SourceLocation PragmaLoc); + void ActOnPragmaMSPointersToMembers( + LangOptions::PragmaMSPointersToMembersKind Kind, + SourceLocation PragmaLoc); /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index ecb6184..b3a2b86 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -4021,6 +4021,33 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { if (Arg *A = Args.getLastArg(options::OPT_show_includes)) A->render(Args, CmdArgs); + const Driver &D = getToolChain().getDriver(); + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); + Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); + if (MostGeneralArg && BestCaseArg) + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args); + + if (MostGeneralArg) { + Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms); + Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm); + Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv); + + Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg; + Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg; + if (FirstConflict && SecondConflict && FirstConflict != SecondConflict) + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << FirstConflict->getAsString(Args) + << SecondConflict->getAsString(Args); + + if (SingleArg) + CmdArgs.push_back("-fms-memptr-rep=single"); + else if (MultipleArg) + CmdArgs.push_back("-fms-memptr-rep=multiple"); + else + CmdArgs.push_back("-fms-memptr-rep=virtual"); + } + if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) { CmdArgs.push_back("-fdiagnostics-format"); if (Args.hasArg(options::OPT__SLASH_fallback)) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 034730f..5320415 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1402,6 +1402,24 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } } + if (Arg *A = Args.getLastArg(OPT_fms_memptr_rep_EQ)) { + LangOptions::PragmaMSPointersToMembersKind InheritanceModel = + llvm::StringSwitch( + A->getValue()) + .Case("single", + LangOptions::PPTMK_FullGeneralitySingleInheritance) + .Case("multiple", + LangOptions::PPTMK_FullGeneralityMultipleInheritance) + .Case("virtual", + LangOptions::PPTMK_FullGeneralityVirtualInheritance) + .Default(LangOptions::PPTMK_BestCase); + if (InheritanceModel == LangOptions::PPTMK_BestCase) + Diags.Report(diag::err_drv_invalid_value) + << "-fms-memptr-rep=" << A->getValue(); + + Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel); + } + // Check if -fopenmp is specified. Opts.OpenMP = Args.hasArg(OPT_fopenmp); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 2655996..8cf2b3f 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -182,8 +182,8 @@ void Parser::HandlePragmaOpenCLExtension() { void Parser::HandlePragmaMSPointersToMembers() { assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); - Sema::PragmaMSPointersToMembersKind RepresentationMethod = - static_cast( + LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = + static_cast( reinterpret_cast(Tok.getAnnotationValue())); SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); @@ -834,9 +834,9 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, } PP.Lex(Tok); - Sema::PragmaMSPointersToMembersKind RepresentationMethod; + LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; if (Arg->isStr("best_case")) { - RepresentationMethod = Sema::PPTMK_BestCase; + RepresentationMethod = LangOptions::PPTMK_BestCase; } else { if (Arg->isStr("full_generality")) { if (Tok.is(tok::comma)) { @@ -854,7 +854,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, // #pragma pointers_to_members(full_generality) implicitly specifies // virtual_inheritance. Arg = 0; - RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance; + RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; } else { PP.Diag(Tok.getLocation(), diag::err_expected_punc) << "full_generality"; @@ -864,11 +864,14 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, if (Arg) { if (Arg->isStr("single_inheritance")) { - RepresentationMethod = Sema::PPTMK_FullGeneralitySingleInheritance; + RepresentationMethod = + LangOptions::PPTMK_FullGeneralitySingleInheritance; } else if (Arg->isStr("multiple_inheritance")) { - RepresentationMethod = Sema::PPTMK_FullGeneralityMultipleInheritance; + RepresentationMethod = + LangOptions::PPTMK_FullGeneralityMultipleInheritance; } else if (Arg->isStr("virtual_inheritance")) { - RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance; + RepresentationMethod = + LangOptions::PPTMK_FullGeneralityVirtualInheritance; } else { PP.Diag(Tok.getLocation(), diag::err_pragma_pointers_to_members_unknown_kind) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index b2cf59b..871e1c9 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -76,7 +76,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CollectStats(false), CodeCompleter(CodeCompleter), CurContext(0), OriginalLexicalContext(0), PackContext(0), MSStructPragmaOn(false), - MSPointerToMemberRepresentationMethod(PPTMK_BestCase), VisContext(0), + MSPointerToMemberRepresentationMethod( + pp.getLangOpts().getMSPointerToMemberRepresentationMethod()), + VisContext(0), IsBuildingRecoveryCallExpr(false), ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0), IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0), diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 9f0eb91..4da14ec 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -288,7 +288,7 @@ void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) { } void Sema::ActOnPragmaMSPointersToMembers( - PragmaMSPointersToMembersKind RepresentationMethod, + LangOptions::PragmaMSPointersToMembersKind RepresentationMethod, SourceLocation PragmaLoc) { MSPointerToMemberRepresentationMethod = RepresentationMethod; ImplicitMSInheritanceAttrLoc = PragmaLoc; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 606a4c0..edf1194 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5087,17 +5087,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, MSInheritanceAttr::Spelling InheritanceModel; switch (MSPointerToMemberRepresentationMethod) { - case PPTMK_BestCase: + case LangOptions::PPTMK_BestCase: InheritanceModel = RD->calculateInheritanceModel(); break; - case PPTMK_FullGeneralitySingleInheritance: + case LangOptions::PPTMK_FullGeneralitySingleInheritance: InheritanceModel = MSInheritanceAttr::Keyword_single_inheritance; break; - case PPTMK_FullGeneralityMultipleInheritance: + case LangOptions::PPTMK_FullGeneralityMultipleInheritance: InheritanceModel = MSInheritanceAttr::Keyword_multiple_inheritance; break; - case PPTMK_FullGeneralityVirtualInheritance: + case LangOptions::PPTMK_FullGeneralityVirtualInheritance: InheritanceModel = MSInheritanceAttr::Keyword_unspecified_inheritance; break; @@ -5106,7 +5106,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, RD->addAttr(MSInheritanceAttr::CreateImplicit( getASTContext(), InheritanceModel, /*BestCase=*/MSPointerToMemberRepresentationMethod == - PPTMK_BestCase, + LangOptions::PPTMK_BestCase, ImplicitMSInheritanceAttrLoc.isValid() ? ImplicitMSInheritanceAttrLoc : RD->getSourceRange())); diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index a1174b6..4b5b603 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -67,6 +67,24 @@ // RUN: %clang_cl /U mymacro -### -- %s 2>&1 | FileCheck -check-prefix=U %s // U: "-U" "mymacro" +// RUN: %clang_cl /vmg -### -- %s 2>&1 | FileCheck -check-prefix=VMG %s +// VMG: "-fms-memptr-rep=virtual" + +// RUN: %clang_cl /vmg /vms -### -- %s 2>&1 | FileCheck -check-prefix=VMS %s +// VMS: "-fms-memptr-rep=single" + +// RUN: %clang_cl /vmg /vmm -### -- %s 2>&1 | FileCheck -check-prefix=VMM %s +// VMM: "-fms-memptr-rep=multiple" + +// RUN: %clang_cl /vmg /vmv -### -- %s 2>&1 | FileCheck -check-prefix=VMV %s +// VMV: "-fms-memptr-rep=virtual" + +// RUN: %clang_cl /vmg /vmb -### -- %s 2>&1 | FileCheck -check-prefix=VMB %s +// VMB: '/vmg' not allowed with '/vmb' + +// RUN: %clang_cl /vmg /vmm /vms -### -- %s 2>&1 | FileCheck -check-prefix=VMX %s +// VMX: '/vms' not allowed with '/vmm' + // RUN: %clang_cl /W0 -### -- %s 2>&1 | FileCheck -check-prefix=W0 %s // W0: -w @@ -197,10 +215,6 @@ // RUN: /u \ // RUN: /V \ // RUN: /vd2 \ -// RUN: /vmb \ -// RUN: /vmm \ -// RUN: /vms \ -// RUN: /vmv \ // RUN: /volatile \ // RUN: /wfoo \ // RUN: /WL \ diff --git a/clang/test/SemaCXX/member-pointer-ms.cpp b/clang/test/SemaCXX/member-pointer-ms.cpp index 422b7cf..e7c4ae9 100644 --- a/clang/test/SemaCXX/member-pointer-ms.cpp +++ b/clang/test/SemaCXX/member-pointer-ms.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s -// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify -DVMB %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMB %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMV -fms-memptr-rep=virtual %s // // This file should also give no diagnostics when run through cl.exe from MSVS // 2012, which supports C++11 and static_assert. It should pass for both 64-bit @@ -18,6 +19,7 @@ struct Foo { int f; }; +#ifdef VMB enum { kSingleDataAlign = 1 * sizeof(int), kSingleFunctionAlign = 1 * sizeof(void *), @@ -43,11 +45,47 @@ enum { kUnspecifiedDataSize = 3 * sizeof(int), kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *), }; +#elif VMV +enum { + // Everything with more than 1 field is 8 byte aligned, except virtual data + // member pointers on x64 (ugh). +#ifdef _M_X64 + kVirtualDataAlign = 4, +#else + kVirtualDataAlign = 8, +#endif + kMultipleDataAlign = kVirtualDataAlign, + kSingleDataAlign = kVirtualDataAlign, + + kUnspecifiedFunctionAlign = 8, + kVirtualFunctionAlign = kUnspecifiedFunctionAlign, + kMultipleFunctionAlign = kUnspecifiedFunctionAlign, + kSingleFunctionAlign = kUnspecifiedFunctionAlign, + + kUnspecifiedDataSize = 3 * sizeof(int), + kVirtualDataSize = kUnspecifiedDataSize, + kMultipleDataSize = kUnspecifiedDataSize, + kSingleDataSize = kUnspecifiedDataSize, + + kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *), + kVirtualFunctionSize = kUnspecifiedFunctionSize, + kMultipleFunctionSize = kUnspecifiedFunctionSize, + kSingleFunctionSize = kUnspecifiedFunctionSize, +}; +#else +#error "test doesn't yet support this mode!" +#endif // incomplete types +#ifdef VMB class __single_inheritance IncSingle; class __multiple_inheritance IncMultiple; class __virtual_inheritance IncVirtual; +#else +class IncSingle; +class IncMultiple; +class IncVirtual; +#endif static_assert(sizeof(int IncSingle::*) == kSingleDataSize, ""); static_assert(sizeof(int IncMultiple::*) == kMultipleDataSize, ""); static_assert(sizeof(int IncVirtual::*) == kVirtualDataSize, ""); @@ -83,9 +121,15 @@ static_assert(sizeof(void (Virtual::*)()) == kVirtualFunctionSize, ""); // Test both declared and defined templates. template class X; +#ifdef VMB template <> class __single_inheritance X; template <> class __multiple_inheritance X; template <> class __virtual_inheritance X; +#else +template <> class X; +template <> class X; +template <> class X; +#endif // Don't declare X. static_assert(sizeof(int X::*) == kSingleDataSize, ""); static_assert(sizeof(int X::*) == kMultipleDataSize, ""); @@ -183,8 +227,10 @@ struct MemPtrInTemplate { void (T::*func_ptr)(); }; +#ifdef VMB int Virtual::*CastTest = reinterpret_cast(&AA::x); // expected-error@-1 {{cannot reinterpret_cast from member pointer type}} +#endif namespace ErrorTest { template struct __single_inheritance A; @@ -202,7 +248,7 @@ struct __multiple_inheritance C {}; // expected-error{{inheritance model does no struct __virtual_inheritance D; struct D : virtual B {}; } - +#ifdef VMB #pragma pointers_to_members(full_generality, multiple_inheritance) struct TrulySingleInheritance; static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, ""); @@ -225,3 +271,4 @@ struct SingleInheritanceAsVirtualBeforePragma {}; static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, ""); #pragma pointers_to_members(single) // expected-error{{unexpected 'single'}} +#endif