Hi rsmith, rnk, aaron.ballman,
Introduce a notion of a 'current representation method' for
pointers-to-members.
When starting out, this is set to 'best case' (representation method is
chosen by examining the class, selecting the smallest representation
that would work given the class defintion or lack thereof).
This pragma allows the translation unit to dictate exactly what
representation to use, similar to how the inheritance model keywords
operate.
http://llvm-reviews.chandlerc.com/D2723
Files:
include/clang/AST/DeclCXX.h
include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticParseKinds.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
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;
+}
+
// 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/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -766,6 +766,8 @@
"missing '(' after '#pragma %0' - ignoring">;
def warn_pragma_expected_rparen : Warning<
"missing ')' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_punc : Warning<
+ "expected ')' or ',' after '#pragma %0' - ignoring">;
def warn_pragma_expected_identifier : Warning<
"expected identifier in '#pragma %0' - ignored">;
def warn_pragma_ms_struct : Warning<
@@ -801,6 +803,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">;
// OpenCL Section 6.8.g
def err_not_opencl_storage_class_specifier : Error<
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 purose
+ /// 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,96 @@
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
}
+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);
+
+ bool HaveRepresentationMethod = false;
+ Sema::PragmaMSPointersToMembersKind RepresentationMethod;
+ if (Arg->isStr("best_case")) {
+ HaveRepresentationMethod = true;
+ RepresentationMethod = Sema::PPTMK_BestCase;
+ } else if (Arg->isStr("full_generality")) {
+ HaveRepresentationMethod = true;
+ RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance;
+ }
+
+ if (HaveRepresentationMethod &&
+ RepresentationMethod != Sema::PPTMK_BestCase) {
+ 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 (!HaveRepresentationMethod ||
+ RepresentationMethod != Sema::PPTMK_BestCase) {
+ 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.isNot(tok::r_paren)) {
+ 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 *Toks = (Token *)PP.getPreprocessorAllocator().Allocate(
+ sizeof(Token) * 1, llvm::alignOf<Token>());
+ new (Toks) Token();
+ Toks[0].startToken();
+ Toks[0].setKind(tok::annot_pragma_ms_pointers_to_members);
+ Toks[0].setLocation(PointersToMembersLoc);
+ Toks[0].setAnnotationValue(
+ reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
+ PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
+ /*OwnsTokens=*/false);
+}
+
/// \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
@@ -109,6 +109,10 @@
MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions));
PP.AddPragmaHandler(MSDetectMismatchHandler.get());
}
+ if (getLangOpts().MSVCCompat) {
+ MSPointersToMembers.reset(new PragmaMSPointersToMembers());
+ PP.AddPragmaHandler(MSPointersToMembers.get());
+ }
CommentSemaHandler.reset(new ActionCommentHandler(actions));
PP.addCommentHandler(CommentSemaHandler.get());
@@ -484,6 +488,10 @@
PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
MSDetectMismatchHandler.reset();
}
+ if (getLangOpts().MSVCCompat) {
+ PP.RemovePragmaHandler(MSPointersToMembers.get());
+ MSPointersToMembers.reset();
+ }
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
FPContractHandler.reset();
@@ -702,6 +710,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),
@@ -211,6 +212,7 @@
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
MSStructPragmaOn = false;
+ MSPointerToMemberRepresentationMethod = PPTMK_BestCase;
// 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 (134):
CHECK-NEXT: ext_delete_void_ptr_operand
CHECK-NEXT: ext_expected_semi_decl_list
CHECK-NEXT: ext_explicit_specialization_storage_class
@@ -115,6 +115,7 @@
CHECK-NEXT: warn_pragma_expected_enable_disable
CHECK-NEXT: warn_pragma_expected_identifier
CHECK-NEXT: warn_pragma_expected_lparen
+CHECK-NEXT: warn_pragma_expected_punc
CHECK-NEXT: warn_pragma_expected_rparen
CHECK-NEXT: warn_pragma_extra_tokens_at_eol
CHECK-NEXT: warn_pragma_ms_struct
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 proceedes 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(full_generality, 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")
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits