Add support for conversions from a pointer-to-derived to a
pointer-to-base. Also, add overload ranking for pointer conversions
(for both pointer-to-void and derived-to-base pointer conversions).
Note that we do not yet diagnose derived-to-base pointer conversion
errors that stem from ambiguous or inacessible base classes. These
aren't handled during overload resolution; rather, when the conversion
is actually used we go ahead and diagnose the error.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58017 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
new file mode 100644
index 0000000..022c804
--- /dev/null
+++ b/lib/Sema/SemaInherit.cpp
@@ -0,0 +1,54 @@
+//===---- SemaInherit.cpp - C++ Inheritance ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ inheritance semantics,
+// including searching the inheritance hierarchy and (eventually)
+// access checking.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+
+/// IsDerivedFrom - Determine whether the class type Derived is
+/// derived from the class type Base, ignoring qualifiers on Base and
+/// Derived. This routine does not assess whether an actual conversion
+/// from a Derived* to a Base* is legal, because it does not account
+/// for ambiguous conversions or conversions to private/protected
+/// bases.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base)
+{
+ Derived = Context.getCanonicalType(Derived).getUnqualifiedType();
+ Base = Context.getCanonicalType(Base).getUnqualifiedType();
+
+ assert(Derived->isRecordType() && "IsDerivedFrom requires a class type");
+ assert(Base->isRecordType() && "IsDerivedFrom requires a class type");
+
+ if (Derived == Base)
+ return false;
+
+ if (const RecordType *DerivedType = Derived->getAsRecordType()) {
+ const CXXRecordDecl *Decl
+ = static_cast<const CXXRecordDecl *>(DerivedType->getDecl());
+ for (unsigned idx = 0; idx < Decl->getNumBases(); ++idx) {
+ const CXXBaseSpecifier *BaseSpec = Decl->getBase(idx);
+ if (Context.getCanonicalType(BaseSpec->getType()) == Base
+ || IsDerivedFrom(BaseSpec->getType(), Base))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // end namespace clang
+