diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-11-10 01:18:17 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-11-10 01:18:17 +0000 |
commit | d777e2845110469182809e4efc577899395805f7 (patch) | |
tree | 68267a297529091ba38222cc5dae574051938afb /lib/Sema/SemaDeclCXX.cpp | |
parent | c4027c82ad4a61f2da1b893ac8fe47bf11e5d50d (diff) |
Diagnostic circular inheritance involving dependent base classes. We
would have diagnosed this at instantiation time anyway, if only we
didn't hang on all of these test cases. Fixes <rdar://problem/12629723>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167651 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f9eb9ebc99..1c3d4f2052 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1018,6 +1018,14 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, return false; } +/// \brief Determine whether we have the same C++ record definition. +/// +/// Used as a helper function in Sema::CheckBaseSpecifier, below. +static bool sameCXXRecordDef(const CXXRecordDecl *BaseDefinition, + void *UserData) { + return (CXXRecordDecl *)UserData != BaseDefinition; +} + /// \brief Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics @@ -1044,13 +1052,32 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - - if (BaseType->isDependentType()) + + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + + if (BaseType->isDependentType()) { + // Make sure that we don't have circular inheritance among our dependent + // bases. For non-dependent bases, the check for completeness below handles + // this. + if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) { + if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() || + ((BaseDecl = BaseDecl->getDefinition()) && + !BaseDecl->forallBases(&sameCXXRecordDef, Class))) { + Diag(BaseLoc, diag::err_circular_inheritance) + << BaseType << Context.getTypeDeclType(Class); + + if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl()) + Diag(BaseDecl->getLocation(), diag::note_previous_decl) + << BaseType; + + return 0; + } + } + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, Class->getTagKind() == TTK_Class, Access, TInfo, EllipsisLoc); - - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + } // Base specifiers must be record types. if (!BaseType->isRecordType()) { |