diff options
author | Erich Keane <erich.keane@intel.com> | 2017-09-15 16:03:35 +0000 |
---|---|---|
committer | Erich Keane <erich.keane@intel.com> | 2017-09-15 16:03:35 +0000 |
commit | 58bd603109e4e6ca214712ca897d024bed07ef0f (patch) | |
tree | f4864509cdc5bb0e7bdf3502de05b680272f11db /clang/lib/AST/DeclCXX.cpp | |
parent | f34537dff8e75704d699bca7b6a03a6949c50c61 (diff) | |
download | bcm5719-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.cpp | 47 |
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); } |