aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-11-10 01:18:17 +0000
committerDouglas Gregor <dgregor@apple.com>2012-11-10 01:18:17 +0000
commitd777e2845110469182809e4efc577899395805f7 (patch)
tree68267a297529091ba38222cc5dae574051938afb /lib/Sema/SemaDeclCXX.cpp
parentc4027c82ad4a61f2da1b893ac8fe47bf11e5d50d (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.cpp35
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()) {