[PATCH] MS ABI: Add support for #pragma pointers_to_members
Aaron Ballman
aaron.ballman at gmail.com
Sat Feb 8 09:44:48 PST 2014
> Index: include/clang/AST/DeclCXX.h
> ===================================================================
> --- include/clang/AST/DeclCXX.h
> +++ include/clang/AST/DeclCXX.h
> @@ -1600,8 +1600,6 @@
>
> /// \brief Returns the inheritance model used for this record.
> MSInheritanceAttr::Spelling getMSInheritanceModel() const;
> - /// \brief Locks-in the inheritance model for this class.
> - void setMSInheritanceModel();
> /// \brief Calculate what the inheritance model would be for this class.
> MSInheritanceAttr::Spelling calculateInheritanceModel() const;
>
> Index: include/clang/Basic/Attr.td
> ===================================================================
> --- include/clang/Basic/Attr.td
> +++ include/clang/Basic/Attr.td
> @@ -99,6 +99,11 @@
> // be dependent.
> class AlignedArgument<string name, bit opt = 0> : Argument<name, opt>;
>
> +// A bool argument with a default value
> +class DefaultBoolArgument<string name, int default> : BoolArgument<name, 1> {
> + int Default = default;
> +}
This should probably be using a bit instead of an int.
> +
> // An integer argument with a default value
> class DefaultIntArgument<string name, int default> : IntArgument<name, 1> {
> int Default = default;
> @@ -1397,6 +1402,7 @@
>
> def MSInheritance : InheritableAttr {
> let LangOpts = [MicrosoftExt];
> + let Args = [DefaultBoolArgument<"BestCase", 1>];
> let Spellings = [Keyword<"__single_inheritance">,
> Keyword<"__multiple_inheritance">,
> Keyword<"__virtual_inheritance">,
> Index: include/clang/Basic/DiagnosticGroups.td
> ===================================================================
> --- include/clang/Basic/DiagnosticGroups.td
> +++ include/clang/Basic/DiagnosticGroups.td
> @@ -343,8 +343,11 @@
> def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
> def UnknownAttributes : DiagGroup<"unknown-attributes">;
> def IgnoredAttributes : DiagGroup<"ignored-attributes">;
> +def IgnoredPragmas : DiagGroup<"ignored-pragmas">;
> def Attributes : DiagGroup<"attributes", [UnknownAttributes,
> IgnoredAttributes]>;
> +def Pragmas : DiagGroup<"pragmas", [UnknownPragmas,
> + IgnoredPragmas]>;
> def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
> [CXX98CompatUnnamedTypeTemplateArgs]>;
> def UnsupportedFriend : DiagGroup<"unsupported-friend">;
> Index: include/clang/Basic/DiagnosticParseKinds.td
> ===================================================================
> --- include/clang/Basic/DiagnosticParseKinds.td
> +++ include/clang/Basic/DiagnosticParseKinds.td
> @@ -763,27 +763,33 @@
> // Language specific pragmas
> // - Generic warnings
> def warn_pragma_expected_lparen : Warning<
> - "missing '(' after '#pragma %0' - ignoring">;
> + "missing '(' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
> def warn_pragma_expected_rparen : Warning<
> - "missing ')' after '#pragma %0' - ignoring">;
> + "missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
> +def warn_pragma_expected_punc : Warning<
> + "expected ')' or ',' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
> def warn_pragma_expected_identifier : Warning<
> - "expected identifier in '#pragma %0' - ignored">;
> + "expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
> def warn_pragma_ms_struct : Warning<
> - "incorrect use of '#pragma ms_struct on|off' - ignored">;
> + "incorrect use of '#pragma ms_struct on|off' - ignored">, InGroup<IgnoredPragmas>;
> def warn_pragma_extra_tokens_at_eol : Warning<
> - "extra tokens at end of '#pragma %0' - ignored">;
> + "extra tokens at end of '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
> // - #pragma options
> def warn_pragma_options_expected_align : Warning<
> - "expected 'align' following '#pragma options' - ignored">;
> + "expected 'align' following '#pragma options' - ignored">,
> + InGroup<IgnoredPragmas>;
> def warn_pragma_align_expected_equal : Warning<
> - "expected '=' following '#pragma %select{align|options align}0' - ignored">;
> + "expected '=' following '#pragma %select{align|options align}0' - ignored">,
> + InGroup<IgnoredPragmas>;
> def warn_pragma_align_invalid_option : Warning<
> - "invalid alignment option in '#pragma %select{align|options align}0' - ignored">;
> + "invalid alignment option in '#pragma %select{align|options align}0' - ignored">,
> + InGroup<IgnoredPragmas>;
> // - #pragma pack
> def warn_pragma_pack_invalid_action : Warning<
> - "unknown action for '#pragma pack' - ignored">;
> + "unknown action for '#pragma pack' - ignored">, InGroup<IgnoredPragmas>;
> def warn_pragma_pack_malformed : Warning<
> - "expected integer or identifier in '#pragma pack' - ignored">;
> + "expected integer or identifier in '#pragma pack' - ignored">,
> + InGroup<IgnoredPragmas>;
> // - #pragma unused
> def warn_pragma_unused_expected_var : Warning<
> "expected '#pragma unused' argument to be a variable name">;
> @@ -801,6 +807,9 @@
> def err_pragma_detect_mismatch_malformed : Error<
> "pragma detect_mismatch is malformed; it requires two comma-separated "
> "string literals">;
> +// - #pragma pointers_to_members
> +def err_pragma_pointers_to_members_unknown_kind : Error<
> + "unknown kind of inheritance model">;
I agree with Richard that this should probably list what inheritance
model was specified.
>
> // OpenCL Section 6.8.g
> def err_not_opencl_storage_class_specifier : Error<
> Index: include/clang/Basic/DiagnosticSemaKinds.td
> ===================================================================
> --- include/clang/Basic/DiagnosticSemaKinds.td
> +++ include/clang/Basic/DiagnosticSemaKinds.td
> @@ -479,7 +479,7 @@
> def warn_pragma_pack_pop_identifer_and_alignment : Warning<
> "specifying both a name and alignment to 'pop' is undefined">;
> def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
> -def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not be used with dynamic classes or structures">, InGroup<IgnoredAttributes>;
> +def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not be used with dynamic classes or structures">, InGroup<IgnoredPragmas>;
>
> def warn_pragma_unused_undeclared_var : Warning<
> "undeclared variable %0 used as an argument for '#pragma unused'">;
> Index: include/clang/Basic/TokenKinds.def
> ===================================================================
> --- include/clang/Basic/TokenKinds.def
> +++ include/clang/Basic/TokenKinds.def
> @@ -673,6 +673,11 @@
> // handles them.
> ANNOTATION(pragma_fp_contract)
>
> +// Annotation for #pragma pointers_to_members...
> +// The lexer produces these so that they only take effect when the parser
> +// handles them.
> +ANNOTATION(pragma_ms_pointers_to_members)
> +
> // Annotation for #pragma OPENCL EXTENSION...
> // The lexer produces these so that they only take effect when the parser
> // handles them.
> Index: include/clang/Parse/Parser.h
> ===================================================================
> --- include/clang/Parse/Parser.h
> +++ include/clang/Parse/Parser.h
> @@ -155,6 +155,7 @@
> OwningPtr<PragmaHandler> OpenMPHandler;
> OwningPtr<PragmaHandler> MSCommentHandler;
> OwningPtr<PragmaHandler> MSDetectMismatchHandler;
> + OwningPtr<PragmaHandler> MSPointersToMembers;
>
> /// Whether the '>' token acts as an operator or not. This will be
> /// true except when we are parsing an expression within a C++
> @@ -457,6 +458,8 @@
> /// #pragma comment...
> void HandlePragmaMSComment();
>
> + void HandlePragmaMSPointersToMembers();
> +
> /// \brief Handle the annotation token produced for
> /// #pragma align...
> void HandlePragmaAlign();
> Index: include/clang/Sema/Sema.h
> ===================================================================
> --- include/clang/Sema/Sema.h
> +++ include/clang/Sema/Sema.h
> @@ -262,6 +262,16 @@
>
> 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;
> +
> /// VisContext - Manages the stack for \#pragma GCC visibility.
> void *VisContext; // Really a "PragmaVisStack*"
>
> @@ -1864,7 +1874,7 @@
> DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
> unsigned AttrSpellingListIndex);
> MSInheritanceAttr *
> - mergeMSInheritanceAttr(Decl *D, SourceRange Range,
> + mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
> unsigned AttrSpellingListIndex,
> MSInheritanceAttr::Spelling SemanticSpelling);
> FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range,
> @@ -2577,7 +2587,7 @@
> unsigned ArgNum, StringRef &Str,
> SourceLocation *ArgLocation = 0);
> bool checkMSInheritanceAttrOnDefinition(
> - CXXRecordDecl *RD, SourceRange Range,
> + CXXRecordDecl *RD, SourceRange Range, bool BestCase,
> MSInheritanceAttr::Spelling SemanticSpelling);
>
> void CheckAlignasUnderalignment(Decl *D);
> @@ -6970,6 +6980,11 @@
> /// \#pragma comment(kind, "arg").
> void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg);
>
> + /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
> + /// pointers_to_members(representation method[, general purpose
> + /// representation]).
> + void ActOnPragmaMSPointersToMembers(PragmaMSPointersToMembersKind Kind);
> +
> /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
> void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
>
> Index: lib/AST/MicrosoftCXXABI.cpp
> ===================================================================
> --- lib/AST/MicrosoftCXXABI.cpp
> +++ lib/AST/MicrosoftCXXABI.cpp
> @@ -109,14 +109,6 @@
> return IA->getSemanticSpelling();
> }
>
> -void CXXRecordDecl::setMSInheritanceModel() {
> - if (hasAttr<MSInheritanceAttr>())
> - return;
> -
> - addAttr(MSInheritanceAttr::CreateImplicit(
> - getASTContext(), calculateInheritanceModel(), getSourceRange()));
> -}
> -
> // Returns the number of pointer and integer slots used to represent a member
> // pointer in the MS C++ ABI.
> //
> Index: lib/Parse/ParseDeclCXX.cpp
> ===================================================================
> --- lib/Parse/ParseDeclCXX.cpp
> +++ lib/Parse/ParseDeclCXX.cpp
> @@ -2620,6 +2620,11 @@
> continue;
> }
>
> + if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) {
> + HandlePragmaMSPointersToMembers();
> + continue;
> + }
> +
> // If we see a namespace here, a close brace was missing somewhere.
> if (Tok.is(tok::kw_namespace)) {
> DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
> Index: lib/Parse/ParsePragma.cpp
> ===================================================================
> --- lib/Parse/ParsePragma.cpp
> +++ lib/Parse/ParsePragma.cpp
> @@ -180,6 +180,14 @@
> }
> }
>
> +void Parser::HandlePragmaMSPointersToMembers() {
> + assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
> + Sema::PragmaMSPointersToMembersKind RepresentationMethod =
> + static_cast<Sema::PragmaMSPointersToMembersKind>(
> + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
> + Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod);
> + ConsumeToken(); // The annotation token.
> +}
>
>
> // #pragma GCC visibility comes in two variants:
> @@ -799,6 +807,94 @@
> /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
> }
>
> +/// \brief Handle '#pragma pointers_to_members'
> +// The grammar for this pragma is as follows:
> +//
> +// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
> +//
> +// #pragma pointers_to_members '(' 'best_case' ')'
> +// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
> +// #pragma pointers_to_members '(' inheritance-model ')'
> +void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
> + PragmaIntroducerKind Introducer,
> + Token &Tok) {
> + SourceLocation PointersToMembersLoc = Tok.getLocation();
> + PP.Lex(Tok);
> + if (Tok.isNot(tok::l_paren)) {
> + PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
> + << "pointers_to_members";
> + return;
> + }
> + PP.Lex(Tok);
> + const IdentifierInfo *Arg = Tok.getIdentifierInfo();
> + if (!Arg) {
> + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
> + << "pointers_to_members";
> + return;
> + }
> + PP.Lex(Tok);
> +
> + Sema::PragmaMSPointersToMembersKind RepresentationMethod;
> + if (Arg->isStr("best_case")) {
> + RepresentationMethod = Sema::PPTMK_BestCase;
> + } else {
> + if (Arg->isStr("full_generality")) {
> + if (Tok.is(tok::comma)) {
> + PP.Lex(Tok);
> +
> + Arg = Tok.getIdentifierInfo();
> + if (!Arg) {
> + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
> + << "pointers_to_members";
> + return;
> + }
> + } else if (Tok.isNot(tok::r_paren)) {
> + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc)
> + << "pointers_to_members";
> + return;
> + }
> + }
> +
> + if (Arg->isStr("single_inheritance")) {
> + RepresentationMethod = Sema::PPTMK_FullGeneralitySingleInheritance;
> + } else if (Arg->isStr("multiple_inheritance")) {
> + RepresentationMethod = Sema::PPTMK_FullGeneralityMultipleInheritance;
> + } else if (Arg->isStr("virtual_inheritance")) {
> + RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance;
> + } else if (Tok.is(tok::r_paren)) {
> + RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance;
> + } else {
> + PP.Diag(Tok.getLocation(),
> + diag::err_pragma_pointers_to_members_unknown_kind);
> + return;
> + }
> +
> + if (Tok.isNot(tok::r_paren))
> + PP.Lex(Tok);
> + }
> +
> + if (Tok.isNot(tok::r_paren)) {
> + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
> + << "pointers_to_members";
> + return;
> + }
> +
> + PP.Lex(Tok);
> + if (Tok.isNot(tok::eod)) {
> + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
> + << "pointers_to_members";
> + return;
> + }
> +
> + Token AnnotTok;
> + AnnotTok.startToken();
> + AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
> + AnnotTok.setLocation(PointersToMembersLoc);
> + AnnotTok.setAnnotationValue(
> + reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
> + PP.EnterToken(AnnotTok);
> +}
> +
> /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
> ///
> /// The syntax is:
> Index: lib/Parse/ParsePragma.h
> ===================================================================
> --- lib/Parse/ParsePragma.h
> +++ lib/Parse/ParsePragma.h
> @@ -134,6 +134,13 @@
> Sema &Actions;
> };
>
> +class PragmaMSPointersToMembers : public PragmaHandler {
> +public:
> + explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
> + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
> + Token &FirstToken);
> +};
> +
> } // end namespace clang
>
> #endif
> Index: lib/Parse/ParseStmt.cpp
> ===================================================================
> --- lib/Parse/ParseStmt.cpp
> +++ lib/Parse/ParseStmt.cpp
> @@ -345,6 +345,11 @@
> ProhibitAttributes(Attrs);
> return ParseOpenMPDeclarativeOrExecutableDirective();
>
> + case tok::annot_pragma_ms_pointers_to_members:
> + ProhibitAttributes(Attrs);
> + HandlePragmaMSPointersToMembers();
> + return StmtEmpty();
> +
> }
>
> // If we reached this code, the statement must end in a semicolon.
> @@ -820,6 +825,9 @@
> case tok::annot_pragma_fp_contract:
> HandlePragmaFPContract();
> break;
> + case tok::annot_pragma_ms_pointers_to_members:
> + HandlePragmaMSPointersToMembers();
> + break;
> default:
> checkForPragmas = false;
> break;
> Index: lib/Parse/Parser.cpp
> ===================================================================
> --- lib/Parse/Parser.cpp
> +++ lib/Parse/Parser.cpp
> @@ -108,6 +108,8 @@
> PP.AddPragmaHandler(MSCommentHandler.get());
> MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions));
> PP.AddPragmaHandler(MSDetectMismatchHandler.get());
> + MSPointersToMembers.reset(new PragmaMSPointersToMembers());
> + PP.AddPragmaHandler(MSPointersToMembers.get());
> }
>
> CommentSemaHandler.reset(new ActionCommentHandler(actions));
> @@ -483,6 +485,8 @@
> MSCommentHandler.reset();
> PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
> MSDetectMismatchHandler.reset();
> + PP.RemovePragmaHandler(MSPointersToMembers.get());
> + MSPointersToMembers.reset();
> }
>
> PP.RemovePragmaHandler("STDC", FPContractHandler.get());
> @@ -702,6 +706,9 @@
> case tok::annot_pragma_openmp:
> ParseOpenMPDeclarativeDirective();
> return DeclGroupPtrTy();
> + case tok::annot_pragma_ms_pointers_to_members:
> + HandlePragmaMSPointersToMembers();
> + return DeclGroupPtrTy();
> case tok::semi:
> // Either a C++11 empty-declaration or attribute-declaration.
> SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
> Index: lib/Sema/Sema.cpp
> ===================================================================
> --- lib/Sema/Sema.cpp
> +++ lib/Sema/Sema.cpp
> @@ -75,7 +75,8 @@
> Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
> CollectStats(false), CodeCompleter(CodeCompleter),
> CurContext(0), OriginalLexicalContext(0),
> - PackContext(0), MSStructPragmaOn(false), VisContext(0),
> + PackContext(0), MSStructPragmaOn(false),
> + MSPointerToMemberRepresentationMethod(PPTMK_BestCase), VisContext(0),
> IsBuildingRecoveryCallExpr(false),
> ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
> IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
> @@ -210,7 +211,6 @@
> delete I->second;
> if (PackContext) FreePackedContext();
> if (VisContext) FreeVisContext();
> - MSStructPragmaOn = false;
> // Kill all the active scopes.
> for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
> delete FunctionScopes[I];
> Index: lib/Sema/SemaAttr.cpp
> ===================================================================
> --- lib/Sema/SemaAttr.cpp
> +++ lib/Sema/SemaAttr.cpp
> @@ -287,6 +287,11 @@
> Consumer.HandleDetectMismatch(Name, Value);
> }
>
> +void Sema::ActOnPragmaMSPointersToMembers(
> + PragmaMSPointersToMembersKind RepresentationMethod) {
> + MSPointerToMemberRepresentationMethod = RepresentationMethod;
> +}
> +
> void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
> SourceLocation PragmaLoc) {
>
> Index: lib/Sema/SemaDecl.cpp
> ===================================================================
> --- lib/Sema/SemaDecl.cpp
> +++ lib/Sema/SemaDecl.cpp
> @@ -1963,7 +1963,8 @@
> NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
> AttrSpellingListIndex);
> else if (MSInheritanceAttr *IA = dyn_cast<MSInheritanceAttr>(Attr))
> - NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), AttrSpellingListIndex,
> + NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
> + AttrSpellingListIndex,
> IA->getSemanticSpelling());
> else if (isa<AlignedAttr>(Attr))
> // AlignedAttrs are handled separately, because we need to handle all
> @@ -12152,7 +12153,7 @@
>
> if (const MSInheritanceAttr *IA = Record->getAttr<MSInheritanceAttr>())
> checkMSInheritanceAttrOnDefinition(cast<CXXRecordDecl>(Record),
> - IA->getRange(),
> + IA->getRange(), IA->getBestCase(),
> IA->getSemanticSpelling());
> }
>
> Index: lib/Sema/SemaDeclAttr.cpp
> ===================================================================
> --- lib/Sema/SemaDeclAttr.cpp
> +++ lib/Sema/SemaDeclAttr.cpp
> @@ -2873,7 +2873,7 @@
> }
>
> bool Sema::checkMSInheritanceAttrOnDefinition(
> - CXXRecordDecl *RD, SourceRange Range,
> + CXXRecordDecl *RD, SourceRange Range, bool BestCase,
> MSInheritanceAttr::Spelling SemanticSpelling) {
> assert(RD->hasDefinition() && "RD has no definition!");
>
> @@ -2886,8 +2886,13 @@
> if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance)
> return false;
>
> - if (RD->calculateInheritanceModel() == SemanticSpelling)
> - return false;
> + if (BestCase) {
> + if (RD->calculateInheritanceModel() == SemanticSpelling)
> + return false;
> + } else {
> + if (RD->calculateInheritanceModel() <= SemanticSpelling)
> + return false;
> + }
>
> Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
> << 0 /*definition*/;
> @@ -3705,7 +3710,8 @@
> return;
> }
> MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
> - D, Attr.getRange(), Attr.getAttributeSpellingListIndex(),
> + D, Attr.getRange(), /*BestCase=*/true,
> + Attr.getAttributeSpellingListIndex(),
> (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling());
> if (IA)
> D->addAttr(IA);
> @@ -3886,7 +3892,7 @@
> }
>
> MSInheritanceAttr *
> -Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range,
> +Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
> unsigned AttrSpellingListIndex,
> MSInheritanceAttr::Spelling SemanticSpelling) {
> if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
> @@ -3900,7 +3906,8 @@
>
> CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
> if (RD->hasDefinition()) {
> - if (checkMSInheritanceAttrOnDefinition(RD, Range, SemanticSpelling)) {
> + if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
> + SemanticSpelling)) {
> return 0;
> }
> } else {
> @@ -3917,7 +3924,7 @@
> }
>
> return ::new (Context)
> - MSInheritanceAttr(Range, Context, AttrSpellingListIndex);
> + MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
> }
>
> /// Handles semantic checking for features that are common to all attributes,
> Index: lib/Sema/SemaType.cpp
> ===================================================================
> --- lib/Sema/SemaType.cpp
> +++ lib/Sema/SemaType.cpp
> @@ -5081,7 +5081,33 @@
> if (!MPTy->getClass()->isDependentType()) {
> RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
>
> - MPTy->getMostRecentCXXRecordDecl()->setMSInheritanceModel();
> + CXXRecordDecl *RD = MPTy->getMostRecentCXXRecordDecl();
> + if (!RD->hasAttr<MSInheritanceAttr>()) {
> + MSInheritanceAttr::Spelling InheritanceModel;
> +
> + switch (MSPointerToMemberRepresentationMethod) {
> + case PPTMK_BestCase:
> + InheritanceModel = RD->calculateInheritanceModel();
> + break;
> + case PPTMK_FullGeneralitySingleInheritance:
> + InheritanceModel = MSInheritanceAttr::Keyword_single_inheritance;
> + break;
> + case PPTMK_FullGeneralityMultipleInheritance:
> + InheritanceModel =
> + MSInheritanceAttr::Keyword_multiple_inheritance;
> + break;
> + case PPTMK_FullGeneralityVirtualInheritance:
> + InheritanceModel =
> + MSInheritanceAttr::Keyword_unspecified_inheritance;
> + break;
> + }
> +
> + RD->addAttr(MSInheritanceAttr::CreateImplicit(
> + getASTContext(), InheritanceModel,
> + /*BestCase=*/MSPointerToMemberRepresentationMethod ==
> + PPTMK_BestCase,
> + RD->getSourceRange()));
> + }
> }
> }
> }
> Index: test/Misc/warning-flags.c
> ===================================================================
> --- test/Misc/warning-flags.c
> +++ test/Misc/warning-flags.c
> @@ -18,7 +18,7 @@
>
> The list of warnings below should NEVER grow. It should gradually shrink to 0.
>
> -CHECK: Warnings without flags (133):
> +CHECK: Warnings without flags (123):
> CHECK-NEXT: ext_delete_void_ptr_operand
> CHECK-NEXT: ext_expected_semi_decl_list
> CHECK-NEXT: ext_explicit_specialization_storage_class
> @@ -108,21 +108,11 @@
> CHECK-NEXT: warn_pp_convert_rhs_to_positive
> CHECK-NEXT: warn_pp_expr_overflow
> CHECK-NEXT: warn_pp_line_decimal
> -CHECK-NEXT: warn_pragma_align_expected_equal
> -CHECK-NEXT: warn_pragma_align_invalid_option
> CHECK-NEXT: warn_pragma_debug_unexpected_command
> CHECK-NEXT: warn_pragma_expected_colon
> CHECK-NEXT: warn_pragma_expected_enable_disable
> -CHECK-NEXT: warn_pragma_expected_identifier
> -CHECK-NEXT: warn_pragma_expected_lparen
> -CHECK-NEXT: warn_pragma_expected_rparen
> -CHECK-NEXT: warn_pragma_extra_tokens_at_eol
> -CHECK-NEXT: warn_pragma_ms_struct
> CHECK-NEXT: warn_pragma_options_align_reset_failed
> -CHECK-NEXT: warn_pragma_options_expected_align
> -CHECK-NEXT: warn_pragma_pack_invalid_action
> CHECK-NEXT: warn_pragma_pack_invalid_alignment
> -CHECK-NEXT: warn_pragma_pack_malformed
> CHECK-NEXT: warn_pragma_pack_pop_failed
> CHECK-NEXT: warn_pragma_pack_pop_identifer_and_alignment
> CHECK-NEXT: warn_pragma_pack_show
> Index: test/SemaCXX/member-pointer-ms.cpp
> ===================================================================
> --- test/SemaCXX/member-pointer-ms.cpp
> +++ test/SemaCXX/member-pointer-ms.cpp
> @@ -202,3 +202,24 @@
> struct __virtual_inheritance D;
> struct D : virtual B {};
> }
> +
> +#pragma pointers_to_members(full_generality, multiple_inheritance)
> +struct TrulySingleInheritance;
> +static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, "");
> +#pragma pointers_to_members(best_case)
> +// This definition shouldn't conflict with the increased generality that the
> +// multiple_inheritance model gave to TrulySingleInheritance.
> +struct TrulySingleInheritance {};
> +
> +// Even if a definition proceeds the first mention of a pointer to member, we
> +// still give the record the fully general representation.
> +#pragma pointers_to_members(full_generality, virtual_inheritance)
> +struct SingleInheritanceAsVirtualAfterPragma {};
> +static_assert(sizeof(int SingleInheritanceAsVirtualAfterPragma::*) == 12, "");
> +
> +#pragma pointers_to_members(best_case)
> +
> +// The above holds even if the pragma comes after the definition.
> +struct SingleInheritanceAsVirtualBeforePragma {};
> +#pragma pointers_to_members(virtual_inheritance)
> +static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, "");
> Index: utils/TableGen/ClangAttrEmitter.cpp
> ===================================================================
> --- utils/TableGen/ClangAttrEmitter.cpp
> +++ utils/TableGen/ClangAttrEmitter.cpp
> @@ -982,6 +982,9 @@
> Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
> else if (ArgName == "IdentifierArgument")
> Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
> + else if (ArgName == "DefaultBoolArgument")
> + Ptr = new DefaultSimpleArgument(Arg, Attr, "bool",
> + Arg.getValueAsInt("Default"));
> else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
> "bool");
> else if (ArgName == "DefaultIntArgument")
>
It seems like there are two commits in here -- one with the MS
inheritance functionality, and one with ms struct changes; can you
commit them separately for bookkeeping purposes?
Aside from the very minor nits, LGTM!
~Aaron
On Fri, Feb 7, 2014 at 8:23 PM, David Majnemer <david.majnemer at gmail.com> wrote:
> - Address Richard's latest comments.
> - Document the grammar for pointers_to_members
>
> Hi rsmith, rnk, aaron.ballman,
>
> http://llvm-reviews.chandlerc.com/D2723
>
> CHANGE SINCE LAST DIFF
> http://llvm-reviews.chandlerc.com/D2723?vs=6949&id=6950#toc
>
> Files:
> include/clang/AST/DeclCXX.h
> include/clang/Basic/Attr.td
> include/clang/Basic/DiagnosticGroups.td
> include/clang/Basic/DiagnosticParseKinds.td
> include/clang/Basic/DiagnosticSemaKinds.td
> include/clang/Basic/TokenKinds.def
> include/clang/Parse/Parser.h
> include/clang/Sema/Sema.h
> lib/AST/MicrosoftCXXABI.cpp
> lib/Parse/ParseDeclCXX.cpp
> lib/Parse/ParsePragma.cpp
> lib/Parse/ParsePragma.h
> lib/Parse/ParseStmt.cpp
> lib/Parse/Parser.cpp
> lib/Sema/Sema.cpp
> lib/Sema/SemaAttr.cpp
> lib/Sema/SemaDecl.cpp
> lib/Sema/SemaDeclAttr.cpp
> lib/Sema/SemaType.cpp
> test/Misc/warning-flags.c
> test/SemaCXX/member-pointer-ms.cpp
> utils/TableGen/ClangAttrEmitter.cpp
More information about the cfe-commits
mailing list