aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
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()) {