From: Douglas Gregor Date: Fri, 24 Oct 2008 16:17:19 +0000 (+0000) Subject: Some cleanups for the ambiguous derived-to-base conversion checks X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0575d4ab561b4b2905c6ef614a7f7a87be26e64f;p=clang Some cleanups for the ambiguous derived-to-base conversion checks git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58096 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ab5b7b0b00..ef34a10534 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -798,8 +798,8 @@ public: bool IsDerivedFrom(QualType Derived, QualType Base); bool IsDerivedFrom(QualType Derived, QualType Base, BasePaths &Paths); - bool CheckDerivedToBaseConversion(SourceLocation Loc, SourceRange Range, - QualType Derived, QualType Base); + bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range); // Objective-C declarations. virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5c62a936f1..fa81f118c7 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -287,9 +287,10 @@ Sema::CheckReinterpretCast(SourceLocation OpLoc, Expr *&SrcExpr, // object pointers. } -/// Check if the pointer conversion from SrcType to DestType casts away -/// constness as defined in C++ 5.2.11p8ff. This is used by the cast checkers. -/// Both arguments must denote pointer types. +/// CastsAwayConstness - Check if the pointer conversion from SrcType +/// to DestType casts away constness as defined in C++ +/// 5.2.11p8ff. This is used by the cast checkers. Both arguments +/// must denote pointer types. bool Sema::CastsAwayConstness(QualType SrcType, QualType DestType) { diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp index 256ee24e1c..a676b64ff8 100644 --- a/lib/Sema/SemaInherit.cpp +++ b/lib/Sema/SemaInherit.cpp @@ -24,13 +24,15 @@ #include #include -namespace clang { +using namespace clang; /// isAmbiguous - Determines whether the set of paths provided is /// ambiguous, i.e., there are two or more paths that refer to /// different base class subobjects of the same type. BaseType must be /// an unqualified, canonical class type. bool BasePaths::isAmbiguous(QualType BaseType) { + assert(BaseType->isCanonical() && "Base type must be the canonical type"); + assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified"); std::pair& Subobjects = ClassSubobjects[BaseType]; return Subobjects.second + (Subobjects.first? 1 : 0) > 1; } @@ -141,8 +143,8 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, BasePaths &Paths) { /// if there is an error, and Range is the source range to highlight /// if there is an error. bool -Sema::CheckDerivedToBaseConversion(SourceLocation Loc, SourceRange Range, - QualType Derived, QualType Base) { +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range) { // First, determine whether the path from Derived to Base is // ambiguous. This is slightly more expensive than checking whether // the Derived to Base conversion exists, because here we need to @@ -153,47 +155,43 @@ Sema::CheckDerivedToBaseConversion(SourceLocation Loc, SourceRange Range, if (!DerivationOkay) return true; - if (Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { - // We know that the derived-to-base conversion is - // ambiguous. Perform the derived-to-base search just one more - // time to compute all of the possible paths so that we can print - // them out. This is more expensive than any of the previous - // derived-to-base checks we've done, but at this point we know - // we'll be issuing a diagnostic so performance isn't as much of - // an issue. - Paths.clear(); - Paths.setRecordingPaths(true); - bool StillOkay = IsDerivedFrom(Derived, Base, Paths); - assert(StillOkay && "Can only be used with a derived-to-base conversion"); - if (!StillOkay) - return true; - - // Build up a textual representation of the ambiguous paths, e.g., - // D -> B -> A, that will be used to illustrate the ambiguous - // conversions in the diagnostic. We only print one of the paths - // to each base class subobject. - std::string PathDisplayStr; - std::set DisplayedPaths; - for (BasePaths::paths_iterator Path = Paths.begin(); - Path != Paths.end(); ++Path) { - if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { - // We haven't displayed a path to this particular base - // class subobject yet. - PathDisplayStr += "\n "; - PathDisplayStr += Derived.getAsString(); - for (BasePath::const_iterator Element = Path->begin(); - Element != Path->end(); ++Element) - PathDisplayStr += " -> " + Element->Base->getType().getAsString(); - } - } + if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) + return false; - Diag(Loc, diag::err_ambiguous_derived_to_base_conv, - Derived.getAsString(), Base.getAsString(), PathDisplayStr, Range); + // We know that the derived-to-base conversion is ambiguous, and + // we're going to produce a diagnostic. Perform the derived-to-base + // search just one more time to compute all of the possible paths so + // that we can print them out. This is more expensive than any of + // the previous derived-to-base checks we've done, but at this point + // performance isn't as much of an issue. + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + assert(StillOkay && "Can only be used with a derived-to-base conversion"); + if (!StillOkay) return true; + + // Build up a textual representation of the ambiguous paths, e.g., + // D -> B -> A, that will be used to illustrate the ambiguous + // conversions in the diagnostic. We only print one of the paths + // to each base class subobject. + std::string PathDisplayStr; + std::set DisplayedPaths; + for (BasePaths::paths_iterator Path = Paths.begin(); + Path != Paths.end(); ++Path) { + if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { + // We haven't displayed a path to this particular base + // class subobject yet. + PathDisplayStr += "\n "; + PathDisplayStr += Derived.getAsString(); + for (BasePath::const_iterator Element = Path->begin(); + Element != Path->end(); ++Element) + PathDisplayStr += " -> " + Element->Base->getType().getAsString(); + } } - - return false; + + Diag(Loc, diag::err_ambiguous_derived_to_base_conv, + Derived.getAsString(), Base.getAsString(), PathDisplayStr, Range); + return true; } -} // end namespace clang - diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 11b9e66576..7c78365686 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -721,9 +721,9 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType) { ToPointeeType->isRecordType()) { // We must have a derived-to-base conversion. Check an // ambiguous or inaccessible conversion. - return CheckDerivedToBaseConversion(From->getExprLoc(), - From->getSourceRange(), - FromPointeeType, ToPointeeType); + return CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, + From->getExprLoc(), + From->getSourceRange()); } }