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
+