[cfe-dev] [PATCH] extend __interface support
David Robins
llvm at davidrobins.net
Sun Aug 12 23:50:33 PDT 2012
Please find attached a patch that extends the support for the
Microsoft-specific __interface keyword, currently supported as an alias
for struct. I do not have commit access, and if this were to be accepted
I would need someone to commit it for me.
This patch adds the semantics of making all member functions defined in
the interface into pure virtuals, as MSVC does
(http://msdn.microsoft.com/en-us/library/50h7kwtb%28v=vs.100%29.aspx).
It is implemented as a keyword which translates to struct with a new
MS-specific attribute "ms_interface", which causes member functions to
be set to pure virtual (it is not an error to declare either on top of
the automatic setting; additional pure/virtual specifiers are ignored as
in MSVC).
The MicrosoftExtension.cpp test is also updated to do an override of a
base interface method not explicitly declared virtual, which would fail
without this change.
Thank you for your comments/consideration.
-------------- next part --------------
Index: test/Parser/MicrosoftExtensions.cpp
===================================================================
--- test/Parser/MicrosoftExtensions.cpp (revision 161741)
+++ test/Parser/MicrosoftExtensions.cpp (working copy)
@@ -174,13 +174,21 @@
__interface MicrosoftInterface;
__interface MicrosoftInterface {
- virtual void foo1() = 0;
+ void foo1() = 0;
virtual void foo2() = 0;
};
+__interface MicrosoftDerivedInterface : public MicrosoftInterface {
+ void foo1();
+ void foo2() override;
+ void foo3();
+};
+
void interface_test() {
MicrosoftInterface* a;
a->foo1();
+ MicrosoftDerivedInterface* b;
+ b->foo2();
}
__int64 x7 = __int64(0);
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td (revision 161741)
+++ include/clang/Basic/Attr.td (working copy)
@@ -832,6 +832,11 @@
let Spellings = [Declspec<"ms_struct">];
}
+def MsInterface : InheritableAttr {
+ let Spellings = [Declspec<"ms_interface">];
+ let Subjects = [CXXRecord];
+}
+
def DLLExport : InheritableAttr {
let Spellings = [Declspec<"dllexport">];
}
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def (revision 161741)
+++ include/clang/Basic/TokenKinds.def (working copy)
@@ -505,6 +505,7 @@
KEYWORD(__single_inheritance , KEYMS)
KEYWORD(__multiple_inheritance , KEYMS)
KEYWORD(__virtual_inheritance , KEYMS)
+KEYWORD(__interface , KEYMS)
ALIAS("__int8" , char , KEYMS)
ALIAS("__int16" , short , KEYMS)
ALIAS("__int32" , int , KEYMS)
@@ -518,7 +519,6 @@
ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
ALIAS("_inline" , inline , KEYMS)
ALIAS("_declspec" , __declspec , KEYMS)
-ALIAS("__interface" , struct , KEYMS)
// Borland Extensions which should be disabled in strict conformance mode.
ALIAS("_pascal" , __pascal , KEYBORLAND)
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp (revision 161741)
+++ lib/Sema/SemaDeclAttr.cpp (working copy)
@@ -932,6 +932,13 @@
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
+static void handleMsInterfaceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ TD->addAttr(::new (S.Context) MsInterfaceAttr(Attr.getRange(), S.Context));
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (!checkAttributeNumArgs(S, Attr, 0))
@@ -4257,6 +4264,9 @@
case AttributeList::AT_MsStruct:
handleMsStructAttr(S, D, Attr);
break;
+ case AttributeList::AT_MsInterface:
+ handleMsInterfaceAttr(S, D, Attr);
+ break;
case AttributeList::AT_Uuid:
handleUuidAttr(S, D, Attr);
break;
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp (revision 161741)
+++ lib/Sema/SemaDecl.cpp (working copy)
@@ -5138,6 +5138,16 @@
NewFD->setImplicitlyInline();
}
+ // if this is a method defined in an __interface, set pure virtual
+ if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>(NewFD->getDeclContext())) {
+ if (Parent->hasAttr<MsInterfaceAttr>()) {
+ const char *PrevSpec = 0;
+ unsigned DiagID = 0;
+ NewFD->setVirtualAsWritten(true);
+ NewFD->setPure(true);
+ }
+ }
+
SetNestedNameSpecifier(NewFD, D);
isExplicitSpecialization = false;
isFunctionTemplateSpecialization = false;
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp (revision 161741)
+++ lib/Parse/ParseDecl.cpp (working copy)
@@ -2637,6 +2637,7 @@
// class-specifier:
case tok::kw_class:
case tok::kw_struct:
+ case tok::kw___interface:
case tok::kw_union: {
tok::TokenKind Kind = Tok.getKind();
ConsumeToken();
@@ -3457,6 +3458,7 @@
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
+ case tok::kw___interface:
case tok::kw_union:
// enum-specifier
case tok::kw_enum:
@@ -3528,6 +3530,7 @@
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
+ case tok::kw___interface:
case tok::kw_union:
// enum-specifier
case tok::kw_enum:
@@ -3666,6 +3669,7 @@
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
+ case tok::kw___interface:
// enum-specifier
case tok::kw_enum:
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp (revision 161741)
+++ lib/Parse/ParseDeclCXX.cpp (working copy)
@@ -1032,7 +1032,7 @@
AccessSpecifier AS,
bool EnteringContext, DeclSpecContext DSC) {
DeclSpec::TST TagType;
- if (TagTokKind == tok::kw_struct)
+ if (TagTokKind == tok::kw_struct || TagTokKind == tok::kw___interface)
TagType = DeclSpec::TST_struct;
else if (TagTokKind == tok::kw_class)
TagType = DeclSpec::TST_class;
@@ -1110,6 +1110,14 @@
Tok.setKind(tok::identifier);
}
+ // __interface is a Microsoft extension that resolves to a struct
+ // with an 'ms_interface' attribute.
+ if (TagTokKind == tok::kw___interface) {
+ attrs.addNewInteger(
+ Actions.getASTContext(),
+ PP.getIdentifierInfo("ms_interface"), StartLoc, 0);
+ }
+
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
More information about the cfe-dev
mailing list