Clang error: ambiguous conversion from derived class A to base class B:C (err_ambiguous_derived_to_base_conv)

From emmtrix Wiki
Jump to navigation Jump to search
Text error: ambiguous conversion from derived class A to base class B:C
Type Error
Category Semantic Issue
Internal Id err_ambiguous_derived_to_base_conv
Internal Message ambiguous conversion from derived class %0 to base class %1:%2
Regular Expression (?:error|fatal error)\: ambiguous conversion from derived class (.*?) to base class (.*?)\:(.*?)
First Commit 2009-03-14 5a8987ca5113 Update tablegen diagnostic files to be in sync with the def files.

Description

The error is issued by the Clang compiler when it encounters a situation where there is ambiguity in converting a pointer or reference from a derived class to a base class. This typically occurs in a multiple inheritance scenario where a derived class inherits from two or more base classes, which in turn have a common base class. The ambiguity arises because the compiler cannot determine, without explicit direction, which path of inheritance should be followed to perform the conversion.

For instance, in a class hierarchy where class F is derived from both D1 and D2, and both D1 and D2 are derived from B, an attempt to implicitly convert a pointer or reference of type F* (or F&) to type B* (or B&) would result in this error. The ambiguity stems from the compiler's inability to deduce whether the conversion should proceed through D1 or D2.

 
AI Generated

Example

In the following example, a class hierarchy is demonstrated where class F inherits from two classes, D1 and D2, both of which are derived from a single base class B. This setup leads to an ambiguity when trying to convert a pointer of type F* to type B*. The compiler cannot unambiguously determine the path for the conversion because there are two possible paths: through D1 or D2. This situation triggers the Clang error message about ambiguous conversion from a derived class to a base class. To resolve this ambiguity and allow the conversion, an explicit directive such as a static cast would be necessary. However, the example also attempts an invalid static cast from a base class pointer B* to a derived class pointer D1*, which is not directly related to the initial error but further illustrates type conversion challenges in C++ with multiple inheritance.  
AI Generated


Flags -xc++

[Try out in Compiler Explorer]

Source
#include <iostream>

using namespace std;

class B {};
class D1 : public B {};
class D2 : public B {};

class F : public D1, public D2 {};

int main() {
    B* b = new F(); // Ambiguous: F -> D1 -> B and F -> D2 -> B
    D1* d = static_cast<D1*>(b); // Attempts cast from B* to D1*
    cout << "Cast succeeded." << endl;
    return 0;
}
Compiler Output
<source>:12:12: error: ambiguous conversion from derived class 'F' to base class 'B':
    class F -> D1 -> B
    class F -> D2 -> B


Clang Internals (17.0.6)

Git Commit Message

Update tablegen diagnostic files to be in sync with the def files.

llvm-svn: 67004

Used in Clang Sources

This section lists all occurrences of the diagnostic within the Clang's codebase. For each occurrence, an auto-extracted snipped from the source code is listed including key elements like control structures, functions, or classes. It should illustrate the conditions under which the diagnostic is activated.

clang/lib/Sema/SemaDeclCXX.cpp (line 3166)

bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath, bool IgnoreAccess) { return CheckDerivedToBaseConversion(Derived, Base, diag::err_upcast_to_inaccessible_base, diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName(), BasePath, IgnoreAccess); }

clang/lib/Sema/SemaOverload.cpp (line 3146)

/// CheckPointerConversion - Check the pointer conversion from the
/// expression From to the type ToType. This routine checks for
/// ambiguous or inaccessible derived-to-base pointer
/// conversions for which IsPointerConversion has already returned
/// true. It returns true and produces a diagnostic if there was an
/// error, or returns false otherwise.
bool Sema::CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath &BasePath, bool IgnoreBaseAccess, bool Diagnose) {
  // ...
  if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
    if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) {
      // ...
      if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) {
        // ...
        if (Diagnose) {
          // ...
          AmbiguousID = diag::err_ambiguous_derived_to_base_conv;

Triggered in Clang Tests

This section lists all internal Clang test cases that trigger the diagnostic.

clang/test/SemaCXX/dynamic-cast.cpp

  • clang/test/SemaCXX/dynamic-cast.cpp:62:9: error: ambiguous conversion from derived class 'F' to base class 'A':
  • clang/test/SemaCXX/dynamic-cast.cpp:63:9: error: ambiguous conversion from derived class 'F' to base class 'A':