Recognize the MS inheritance attributes and turn them into attributes
on the RecordDecl. Persist the MS portability type attributes and
ignore them in Sema rather than the parser.
Patch by João Matos!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157288 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index f437011..72e0c69 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -308,14 +308,6 @@
let Args = [IntArgument<"Priority">];
}
-def DLLExport : InheritableAttr {
- let Spellings = ["dllexport"];
-}
-
-def DLLImport : InheritableAttr {
- let Spellings = ["dllimport"];
-}
-
def ExtVectorType : Attr {
let Spellings = ["ext_vector_type"];
let Args = [ExprArgument<"NumElements">];
@@ -336,10 +328,6 @@
let SemaHandler = 0;
}
-def MsStruct : InheritableAttr {
- let Spellings = ["__ms_struct__"];
-}
-
def Format : InheritableAttr {
let Spellings = ["format"];
let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">,
@@ -816,3 +804,41 @@
let LateParsed = 1;
let TemplateDependent = 1;
}
+
+// Microsoft-related attributes
+
+def MsStruct : InheritableAttr {
+ let Spellings = ["__ms_struct__"];
+}
+
+def DLLExport : InheritableAttr {
+ let Spellings = ["dllexport"];
+}
+
+def DLLImport : InheritableAttr {
+ let Spellings = ["dllimport"];
+}
+
+def Win64 : InheritableAttr {
+ let Spellings = ["__w64"];
+}
+
+def Ptr32 : InheritableAttr {
+ let Spellings = ["__ptr32"];
+}
+
+def Ptr64 : InheritableAttr {
+ let Spellings = ["__ptr64"];
+}
+
+def SingleInheritance : InheritableAttr {
+ let Spellings = ["__single_inheritance"];
+}
+
+def MultipleInheritance : InheritableAttr {
+ let Spellings = ["__multiple_inheritance"];
+}
+
+def VirtualInheritance : InheritableAttr {
+ let Spellings = ["__virtual_inheritance"];
+}
\ No newline at end of file
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d2292af..fba50ec 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1630,7 +1630,8 @@
"variables and functions|functions and methods|parameters|"
"functions, methods and blocks|functions, methods, and parameters|"
"classes|variables|methods|variables, functions and labels|"
- "fields and global variables|structs}1">;
+ "fields and global variables|structs|"
+ "variables, functions and tag types}1">;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{functions|unions|"
"variables and functions|functions and methods|parameters|"
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 9ea2c18..7c800df 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -496,6 +496,9 @@
KEYWORD(__int64 , KEYMS)
KEYWORD(__if_exists , KEYMS)
KEYWORD(__if_not_exists , KEYMS)
+KEYWORD(__single_inheritance , KEYMS)
+KEYWORD(__multiple_inheritance , KEYMS)
+KEYWORD(__virtual_inheritance , KEYMS)
ALIAS("__int8" , char , KEYMS)
ALIAS("__int16" , short , KEYMS)
ALIAS("__int32" , int , KEYMS)
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 814b45a..f314376 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1859,6 +1859,7 @@
SourceLocation *endLoc = 0);
void ParseMicrosoftDeclSpec(ParsedAttributes &attrs);
void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
void ParseOpenCLAttributes(ParsedAttributes &attrs);
void ParseOpenCLQualifiers(DeclSpec &DS);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index c3ffd9e..ac63780 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -343,10 +343,6 @@
Tok.is(tok::kw___unaligned)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) ||
- Tok.is(tok::kw___ptr32))
- // FIXME: Support these properly!
- continue;
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
SourceLocation(), 0, 0, true);
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 0b5c396..c75e138 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -900,6 +900,17 @@
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
+void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
+ while (Tok.is(tok::kw___single_inheritance) ||
+ Tok.is(tok::kw___multiple_inheritance) ||
+ Tok.is(tok::kw___virtual_inheritance)) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, false);
+ }
+}
+
/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
/// until we reach the start of a definition or see a token that
@@ -985,6 +996,12 @@
while (Tok.is(tok::kw___declspec))
ParseMicrosoftDeclSpec(attrs);
+ // Parse inheritance specifiers.
+ if (Tok.is(tok::kw___single_inheritance) ||
+ Tok.is(tok::kw___multiple_inheritance) ||
+ Tok.is(tok::kw___virtual_inheritance))
+ ParseMicrosoftInheritanceClassAttributes(attrs);
+
// If C++0x attributes exist here, parse them.
// FIXME: Are we consistent with the ordering of parsing of different
// styles of attributes?
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 6d0e30c..ff25645 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -3773,6 +3773,38 @@
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
}
+static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (S.LangOpts.MicrosoftExt) {
+ AttributeList::Kind Kind = Attr.getKind();
+ if (Kind == AttributeList::AT_single_inheritance)
+ D->addAttr(
+ ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context));
+ else if (Kind == AttributeList::AT_multiple_inheritance)
+ D->addAttr(
+ ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context));
+ else if (Kind == AttributeList::AT_virtual_inheritance)
+ D->addAttr(
+ ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context));
+ } else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
+static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (S.LangOpts.MicrosoftExt) {
+ AttributeList::Kind Kind = Attr.getKind();
+ if (Kind == AttributeList::AT_ptr32)
+ D->addAttr(
+ ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context));
+ else if (Kind == AttributeList::AT_ptr64)
+ D->addAttr(
+ ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context));
+ else if (Kind == AttributeList::AT_w64)
+ D->addAttr(
+ ::new (S.Context) Win64Attr(Attr.getRange(), S.Context));
+ } else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
//===----------------------------------------------------------------------===//
// Top Level Sema Entry Points
//===----------------------------------------------------------------------===//
@@ -3889,7 +3921,6 @@
handleInitPriorityAttr(S, D, Attr); break;
case AttributeList::AT_packed: handlePackedAttr (S, D, Attr); break;
- case AttributeList::AT_ms_struct: handleMsStructAttr (S, D, Attr); break;
case AttributeList::AT_section: handleSectionAttr (S, D, Attr); break;
case AttributeList::AT_unavailable:
handleAttrWithMessage<UnavailableAttr>(S, D, Attr, "unavailable");
@@ -3949,9 +3980,24 @@
case AttributeList::AT_opencl_kernel_function:
handleOpenCLKernelAttr(S, D, Attr);
break;
+
+ // Microsoft attributes:
+ case AttributeList::AT_ms_struct:
+ handleMsStructAttr(S, D, Attr);
+ break;
case AttributeList::AT_uuid:
handleUuidAttr(S, D, Attr);
break;
+ case AttributeList::AT_single_inheritance:
+ case AttributeList::AT_multiple_inheritance:
+ case AttributeList::AT_virtual_inheritance:
+ handleInheritanceAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_w64:
+ case AttributeList::AT_ptr32:
+ case AttributeList::AT_ptr64:
+ handlePortabilityAttr(S, D, Attr);
+ break;
// Thread safety attributes:
case AttributeList::AT_guarded_var:
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 13a72a5..f795660 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -4028,6 +4028,13 @@
attr.setUsedAsTypeAttr();
break;
+ case AttributeList::AT_w64:
+ case AttributeList::AT_ptr32:
+ case AttributeList::AT_ptr64:
+ // FIXME: don't ignore these
+ attr.setUsedAsTypeAttr();
+ break;
+
case AttributeList::AT_ns_returns_retained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
break;
diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c
index 6b00534..c20bdb6 100644
--- a/test/Parser/MicrosoftExtensions.c
+++ b/test/Parser/MicrosoftExtensions.c
@@ -11,11 +11,11 @@
void * __ptr64 PtrToPtr64(const void *p)
{
- return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p ); // expected-warning {{unknown attribute '__ptr64' ignored}}
+ return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p );
}
void * __ptr32 PtrToPtr32(const void *p)
{
- return((void * __ptr32) (unsigned __int32) (ULONG_PTR)p ); // expected-warning {{unknown attribute '__ptr32' ignored}}
+ return((void * __ptr32) (unsigned __int32) (ULONG_PTR)p );
}
void __forceinline InterlockedBitTestAndSet (long *Base, long Bit)
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index 9404788..6219e29 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -317,3 +317,9 @@
&A::f;
}
}
+
+namespace Inheritance {
+ class __single_inheritance A;
+ class __multiple_inheritance B;
+ class __virtual_inheritance C;
+}