aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/DeclCXX.cpp30
-rw-r--r--lib/AST/MicrosoftMangle.cpp13
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp56
-rw-r--r--lib/AST/Type.cpp14
4 files changed, 72 insertions, 41 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 2f21e4cbd6..c68a16bdae 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -463,13 +463,14 @@ void CXXRecordDecl::markedConstructorConstexpr(CXXConstructorDecl *CD) {
}
void CXXRecordDecl::addedMember(Decl *D) {
- if (!D->isImplicit() &&
- !isa<FieldDecl>(D) &&
- !isa<IndirectFieldDecl>(D) &&
- (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class))
- data().HasOnlyCMembers = false;
-
- // Ignore friends and invalid declarations.
+ if (!D->isImplicit() &&
+ !isa<FieldDecl>(D) &&
+ !isa<IndirectFieldDecl>(D) &&
+ (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
+ cast<TagDecl>(D)->getTagKind() == TTK_Interface))
+ data().HasOnlyCMembers = false;
+
+ // Ignore friends and invalid declarations.
if (D->getFriendObjectKind() || D->isInvalidDecl())
return;
@@ -933,13 +934,14 @@ NotASpecialMember:;
if (Shadow->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName)
data().Conversions.addDecl(Shadow, Shadow->getAccess());
-}
-
-bool CXXRecordDecl::isCLike() const {
- if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull())
- return false;
- if (!hasDefinition())
- return true;
+}
+
+bool CXXRecordDecl::isCLike() const {
+ if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
+ !TemplateOrInstantiation.isNull())
+ return false;
+ if (!hasDefinition())
+ return true;
return isPOD() && data().HasOnlyCMembers;
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 982e3aceec..f0041b2422 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1270,12 +1270,13 @@ void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
switch (T->getDecl()->getTagKind()) {
case TTK_Union:
- Out << 'T';
- break;
- case TTK_Struct:
- Out << 'U';
- break;
- case TTK_Class:
+ Out << 'T';
+ break;
+ case TTK_Struct:
+ case TTK_Interface:
+ Out << 'U';
+ break;
+ case TTK_Class:
Out << 'V';
break;
case TTK_Enum:
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index d5df63f7d1..043e46e9d6 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -2260,12 +2260,28 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
}
// Use the externally-supplied field offset.
- return ExternalFieldOffset;
-}
-
-void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
- uint64_t UnpaddedOffset,
- uint64_t UnpackedOffset,
+ return ExternalFieldOffset;
+}
+
+/// \brief Get diagnostic %select index for tag kind for
+/// field padding diagnostic message.
+/// WARNING: Indexes apply to particular diagnostics only!
+///
+/// \returns diagnostic %select index.
+static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
+{
+ switch (Tag) {
+ case TTK_Struct: return 0;
+ case TTK_Interface: return 1;
+ case TTK_Class: return 2;
+ default: assert("Invalid tag kind for field padding diagnostic!");
+ }
+ return -1;
+}
+
+void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
+ uint64_t UnpaddedOffset,
+ uint64_t UnpackedOffset,
unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
@@ -2288,20 +2304,20 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
if (PadSize % CharBitNum == 0) {
PadSize = PadSize / CharBitNum;
InBits = false;
- }
- if (D->getIdentifier())
- Diag(D->getLocation(), diag::warn_padded_struct_field)
- << (D->getParent()->isStruct() ? 0 : 1) // struct|class
- << Context.getTypeDeclType(D->getParent())
- << PadSize
- << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
- << D->getIdentifier();
- else
- Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
- << (D->getParent()->isStruct() ? 0 : 1) // struct|class
- << Context.getTypeDeclType(D->getParent())
- << PadSize
- << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
+ }
+ if (D->getIdentifier())
+ Diag(D->getLocation(), diag::warn_padded_struct_field)
+ << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
+ << Context.getTypeDeclType(D->getParent())
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
+ << D->getIdentifier();
+ else
+ Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
+ << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
+ << Context.getTypeDeclType(D->getParent())
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
}
// Warn if we packed it unnecessarily. If the alignment is 1 byte don't
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 7445152d62..c54250a479 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -357,9 +357,15 @@ bool Type::isStructureType() const {
return RT->getDecl()->isStruct();
return false;
}
+bool Type::isInterfaceType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->isInterface();
+ return false;
+}
bool Type::isStructureOrClassType() const {
if (const RecordType *RT = getAs<RecordType>())
- return RT->getDecl()->isStruct() || RT->getDecl()->isClass();
+ return RT->getDecl()->isStruct() || RT->getDecl()->isClass() ||
+ RT->getDecl()->isInterface();
return false;
}
bool Type::isVoidPointerType() const {
@@ -1317,6 +1323,7 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
case TST_typename: return ETK_Typename;
case TST_class: return ETK_Class;
case TST_struct: return ETK_Struct;
+ case TST_interface: return ETK_Interface;
case TST_union: return ETK_Union;
case TST_enum: return ETK_Enum;
}
@@ -1327,6 +1334,7 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
switch(TypeSpec) {
case TST_class: return TTK_Class;
case TST_struct: return TTK_Struct;
+ case TST_interface: return TTK_Interface;
case TST_union: return TTK_Union;
case TST_enum: return TTK_Enum;
}
@@ -1339,6 +1347,7 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
switch (Kind) {
case TTK_Class: return ETK_Class;
case TTK_Struct: return ETK_Struct;
+ case TTK_Interface: return ETK_Interface;
case TTK_Union: return ETK_Union;
case TTK_Enum: return ETK_Enum;
}
@@ -1350,6 +1359,7 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
switch (Keyword) {
case ETK_Class: return TTK_Class;
case ETK_Struct: return TTK_Struct;
+ case ETK_Interface: return TTK_Interface;
case ETK_Union: return TTK_Union;
case ETK_Enum: return TTK_Enum;
case ETK_None: // Fall through.
@@ -1367,6 +1377,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
return false;
case ETK_Class:
case ETK_Struct:
+ case ETK_Interface:
case ETK_Union:
case ETK_Enum:
return true;
@@ -1381,6 +1392,7 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
case ETK_Typename: return "typename";
case ETK_Class: return "class";
case ETK_Struct: return "struct";
+ case ETK_Interface: return "__interface";
case ETK_Union: return "union";
case ETK_Enum: return "enum";
}