diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 6b3d472066117ed564c692adb0036e6470647668..93c64805aa9f96065dbe1b681466d202f7d70444 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1600,8 +1600,6 @@ public: /// \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; diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index d2c80b113d44b7735406367b204072d6ae508720..b263c1bc1d6171344731e0e5158310847c5b2bb4 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -99,6 +99,11 @@ class VersionArgument<string name, bit opt = 0> : Argument<name, opt>; // be dependent. class AlignedArgument<string name, bit opt = 0> : Argument<name, opt>; +// A bool argument with a default value +class DefaultBoolArgument<string name, bit default> : BoolArgument<name, 1> { + bit Default = default; +} + // An integer argument with a default value class DefaultIntArgument<string name, int default> : IntArgument<name, 1> { int Default = default; @@ -1397,6 +1402,7 @@ def UPtr : TypeAttr { def MSInheritance : InheritableAttr { let LangOpts = [MicrosoftExt]; + let Args = [DefaultBoolArgument<"BestCase", 1>]; let Spellings = [Keyword<"__single_inheritance">, Keyword<"__multiple_inheritance">, Keyword<"__virtual_inheritance">, diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index b269313fce8958d199612ac7138b1d6fdbe946ea..de07ee8d8fc9fec79a7d333ed50a4c34e08ea074 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -177,6 +177,8 @@ def err_invalid_token_after_declarator_suggest_equal : Error< "invalid %0 at end of declaration; did you mean '='?">; def err_expected_statement : Error<"expected statement">; def err_expected_lparen_after : Error<"expected '(' after '%0'">; +def err_expected_rparen_after : Error<"expected ')' after '%0'">; +def err_expected_punc : Error<"expected ')' or ',' after '%0'">; def err_expected_less_after : Error<"expected '<' after '%0'">; def err_expected_lbrace_in_compound_literal : Error< "expected '{' in compound literal">; @@ -809,6 +811,10 @@ def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; 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< + "unexpected %0, expected to see one of %select{|'best_case', 'full_generality', }1" + "'single_inheritance', 'multiple_inheritance', or 'virtual_inheritance'">; // OpenCL Section 6.8.g def err_not_opencl_storage_class_specifier : Error< diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index a7e27d5e29bad4aa2861db37e7c33e7efd83a257..05c2fa2b27c76996d08fee75ee765903c666cd0c 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -673,6 +673,11 @@ ANNOTATION(pragma_redefine_extname) // 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. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index baa890a5408f45f9e3b9498bc8f9fb669b55d7cf..8b9053fa09808a2ef85493cef9c2685c8156f66f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -155,6 +155,7 @@ class Parser : public CodeCompletionHandler { 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 @@ private: /// #pragma comment... void HandlePragmaMSComment(); + void HandlePragmaMSPointersToMembers(); + /// \brief Handle the annotation token produced for /// #pragma align... void HandlePragmaAlign(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index aa6d2246aedde256fd6da2e9398cc0c658eaed5b..85d29da35a36e846e06d4f9d4c872a83781e5e8b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -262,6 +262,19 @@ 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; + + /// \brief Source location for newly created implicit MSInheritanceAttrs + SourceLocation ImplicitMSInheritanceAttrLoc; + /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" @@ -1864,7 +1877,7 @@ public: 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 +2590,7 @@ public: 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 +6983,12 @@ public: /// \#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, + SourceLocation PragmaLoc); + /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value); diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 03d0d505514eabf77fbd28b35bbbd72009ef1517..91ffc63b770972573fd2f9d1eced774764a65fe6 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -109,14 +109,6 @@ CXXRecordDecl::getMSInheritanceModel() const { 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. // diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 083d682428ec53ab20bc4823766eb7bdf5c5d815..5d68453e3fb9e9ffde03ffeb48999aff27c35eb4 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2620,6 +2620,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, 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)); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 41562a44e962791d1137926a464165b0c2b47187..2655996a1fff2d9af1e05f1442755b957823f0f6 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -180,6 +180,14 @@ void Parser::HandlePragmaOpenCLExtension() { } } +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())); + SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); +} // #pragma GCC visibility comes in two variants: @@ -799,6 +807,99 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, /*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::err_pragma_pointers_to_members_unknown_kind) + << Tok.getKind() << /*OnlyInheritanceModels*/ 0; + return; + } + PP.Lex(Tok); + } else if (Tok.is(tok::r_paren)) { + // #pragma pointers_to_members(full_generality) implicitly specifies + // virtual_inheritance. + Arg = 0; + RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance; + } else { + PP.Diag(Tok.getLocation(), diag::err_expected_punc) + << "full_generality"; + return; + } + } + + if (Arg) { + 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 { + PP.Diag(Tok.getLocation(), + diag::err_pragma_pointers_to_members_unknown_kind) + << Arg << /*HasPointerDeclaration*/ 1; + return; + } + } + } + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) + << (Arg ? Arg->getName() : "full_generality"); + 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: diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index b41450f4eadfc98c931dabca85db15006c311c82..734bc8d6349263f8a602c1cf3e007ae1bf18450b 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -134,6 +134,13 @@ private: 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 diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index f2e4ad9f7b12f7620ccecc29dee0db889191a1e7..0be14f07ae858047bc8d7baa37376d7025d4fbcb 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -345,6 +345,11 @@ Retry: 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 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); break; + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + break; default: checkForPragmas = false; break; diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index efa6a1bb592da2ffde684a2db91e6a812901c2f1..a52248f2f9159a2497811b025672560e831f1bc0 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -108,6 +108,8 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) 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 @@ Parser::~Parser() { MSCommentHandler.reset(); PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); MSDetectMismatchHandler.reset(); + PP.RemovePragmaHandler(MSPointersToMembers.get()); + MSPointersToMembers.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -702,6 +706,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, 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(), diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 494fe73ed3f84ec8fb22e16ff34bcf4a20712257..b2cf59b1c8470bf2805071907397407d946c5627 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -75,7 +75,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, 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), diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 499f958744741d2995a6b85ff332177c4183c6fd..9f0eb91d2e40684d03cefe96ebd5a1307a61d87f 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -287,6 +287,13 @@ void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) { Consumer.HandleDetectMismatch(Name, Value); } +void Sema::ActOnPragmaMSPointersToMembers( + PragmaMSPointersToMembersKind RepresentationMethod, + SourceLocation PragmaLoc) { + MSPointerToMemberRepresentationMethod = RepresentationMethod; + ImplicitMSInheritanceAttrLoc = PragmaLoc; +} + void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, SourceLocation PragmaLoc) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b42b502b097da6d3495dab78910f4a04b0235593..17e0f38e07de3af55f01dd357a7191b62bc9708c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1963,7 +1963,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr, 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 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (const MSInheritanceAttr *IA = Record->getAttr<MSInheritanceAttr>()) checkMSInheritanceAttrOnDefinition(cast<CXXRecordDecl>(Record), - IA->getRange(), + IA->getRange(), IA->getBestCase(), IA->getSemanticSpelling()); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 66591e4bf36035177f9b9cc9a923bde65bbd7538..65fb7266dbf01e68b320a87155ce3c97124f2f6b 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2873,7 +2873,7 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { } 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 @@ bool Sema::checkMSInheritanceAttrOnDefinition( 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 @@ static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) 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 @@ static void handleDLLExportAttr(Sema &S, Decl *D, const AttributeList &Attr) { } 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 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, 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 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, } return ::new (Context) - MSInheritanceAttr(Range, Context, AttrSpellingListIndex); + MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex); } /// Handles semantic checking for features that are common to all attributes, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index f9f6cee994ecfa3fb16636f7cacb5526ff33900d..606a4c090783d1fdb3832703dc9835599e482acc 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -5082,7 +5082,35 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, 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, + ImplicitMSInheritanceAttrLoc.isValid() + ? ImplicitMSInheritanceAttrLoc + : RD->getSourceRange())); + } } } } diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp index 8e8094004f6fcfc7b630d1adc55cc3404976c7da..422b7cfbd18d3393a4c5770c620a49a4f4d81f7e 100644 --- a/test/SemaCXX/member-pointer-ms.cpp +++ b/test/SemaCXX/member-pointer-ms.cpp @@ -202,3 +202,26 @@ struct __multiple_inheritance C {}; // expected-error{{inheritance model does no 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, ""); + +#pragma pointers_to_members(single) // expected-error{{unexpected 'single'}} diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 0d1df4f8ad4a2db7744ae82ebdbe5fb0e6c3317e..26c5faf5932cc63f7baca6783aef08fa39f18427 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -982,6 +982,9 @@ static Argument *createArgument(Record &Arg, StringRef Attr, 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.getValueAsBit("Default")); else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr, "bool"); else if (ArgName == "DefaultIntArgument")