[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