summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
authorErich Keane <erich.keane@intel.com>2017-09-15 16:03:35 +0000
committerErich Keane <erich.keane@intel.com>2017-09-15 16:03:35 +0000
commit58bd603109e4e6ca214712ca897d024bed07ef0f (patch)
treef4864509cdc5bb0e7bdf3502de05b680272f11db /clang/lib/AST/DeclCXX.cpp
parentf34537dff8e75704d699bca7b6a03a6949c50c61 (diff)
downloadbcm5719-llvm-58bd603109e4e6ca214712ca897d024bed07ef0f.tar.gz
bcm5719-llvm-58bd603109e4e6ca214712ca897d024bed07ef0f.zip
Fix the __interface inheritence rules to work better with IUnknown and IDispatch
__interface objects in MSVC are permitted to inherit from __interface types, and interface-like types. Additionally, there are two default interface-like types (IUnknown and IDispatch) that all interface-like types must inherit from. Differential Revision: https://reviews.llvm.org/D37308 llvm-svn: 313364
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
-rw-r--r--clang/lib/AST/DeclCXX.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 5782b7b56c9..d63d42c66ff 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1470,6 +1470,53 @@ bool CXXRecordDecl::isAnyDestructorNoReturn() const {
return false;
}
+bool CXXRecordDecl::isInterfaceLike() const {
+ assert(hasDefinition() && "checking for interface-like without a definition");
+ // All __interfaces are inheritently interface-like.
+ if (isInterface())
+ return true;
+
+ // Interface-like types cannot have a user declared constructor, destructor,
+ // friends, VBases, conversion functions, or fields. Additionally, lambdas
+ // cannot be interface types.
+ if (isLambda() || hasUserDeclaredConstructor() ||
+ hasUserDeclaredDestructor() || !field_empty() || hasFriends() ||
+ getNumVBases() > 0 || conversion_end() - conversion_begin() > 0)
+ return false;
+
+ // No interface-like type can have a method with a definition.
+ for (const auto *const Method : methods())
+ if (Method->isDefined())
+ return false;
+
+ // Check "Special" types.
+ const auto *Uuid = getAttr<UuidAttr>();
+ if (Uuid && isStruct() && getDeclContext()->isTranslationUnit() &&
+ ((getName() == "IUnknown" &&
+ Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") ||
+ (getName() == "IDispatch" &&
+ Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) {
+ if (getNumBases() > 0)
+ return false;
+ return true;
+ }
+
+ // FIXME: Any access specifiers is supposed to make this no longer interface
+ // like.
+
+ // If this isn't a 'special' type, it must have a single interface-like base.
+ if (getNumBases() != 1)
+ return false;
+
+ const auto BaseSpec = *bases_begin();
+ if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public)
+ return false;
+ const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+ if (Base->isInterface() || !Base->isInterfaceLike())
+ return false;
+ return true;
+}
+
void CXXRecordDecl::completeDefinition() {
completeDefinition(nullptr);
}
OpenPOWER on IntegriCloud