diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-15 09:20:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-15 09:20:52 +0000 |
commit | ab15d0e5af616c11b6cbb478c81d0a8eaa9d450a (patch) | |
tree | 6b0df8ec5feaff61900e216906516e88f7cdef18 | |
parent | c07a494b376f75f33759cf09ad188b11ef3fa9d5 (diff) |
When performing a static downcast as part of a static_cast, make sure
that we're dealing with canonical types like the documentation say
(yay, CanQualType). Alas, this is another instance where using
getQualifiers() on a non-canonical QualType got us in trouble.
Good news: with this fix, Clang can now parse all of its own headers!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88848 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 29 | ||||
-rw-r--r-- | test/SemaCXX/static-cast.cpp | 18 |
2 files changed, 34 insertions, 13 deletions
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index d055dd4c58..2ccad80bdc 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -77,8 +77,8 @@ static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind); -static TryCastResult TryStaticDowncast(Sema &Self, QualType SrcType, - QualType DestType, bool CStyle, +static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, + CanQualType DestType, bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, @@ -190,7 +190,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { assert((DestType->isPointerType() || DestType->isMemberPointerType()) && "Destination type is not pointer or pointer to member."); - QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType; + QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), + UnwrappedDestType = Self.Context.getCanonicalType(DestType); llvm::SmallVector<Qualifiers, 8> cv1, cv2; // Find the qualifications. @@ -573,7 +574,9 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, QualType DestPointee = DestReference->getPointeeType(); - return TryStaticDowncast(Self, SrcExpr->getType(), DestPointee, CStyle, + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcExpr->getType()), + Self.Context.getCanonicalType(DestPointee), CStyle, OpRange, SrcExpr->getType(), DestType, msg, Kind); } @@ -601,16 +604,17 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, return TC_NotApplicable; } - return TryStaticDowncast(Self, SrcPointer->getPointeeType(), - DestPointer->getPointeeType(), CStyle, - OpRange, SrcType, DestType, msg, Kind); + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcPointer->getPointeeType()), + Self.Context.getCanonicalType(DestPointer->getPointeeType()), + CStyle, OpRange, SrcType, DestType, msg, Kind); } /// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and /// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to -/// DestType, both of which must be canonical, is possible and allowed. +/// DestType is possible and allowed. TryCastResult -TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, +TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, CastExpr::CastKind &Kind) { @@ -620,7 +624,7 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, return TC_NotApplicable; // Downcast can only happen in class hierarchies, so we need classes. - if (!DestType->isRecordType() || !SrcType->isRecordType()) { + if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) { return TC_NotApplicable; } @@ -676,12 +680,13 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, EE = PI->rend(); EI != EE; ++EI) PathDisplayStr += EI->Base->getType().getAsString() + " -> "; - PathDisplayStr += DestType.getAsString(); + PathDisplayStr += QualType(DestType).getAsString(); } } Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast) - << SrcType.getUnqualifiedType() << DestType.getUnqualifiedType() + << QualType(SrcType).getUnqualifiedType() + << QualType(DestType).getUnqualifiedType() << PathDisplayStr << OpRange; msg = 0; return TC_Failed; diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp index 68f1dff276..d3962727b8 100644 --- a/test/SemaCXX/static-cast.cpp +++ b/test/SemaCXX/static-cast.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify -faccess-control %s - struct A {}; struct B : public A {}; // Single public base. struct C1 : public virtual B {}; // Single virtual base. @@ -162,3 +161,20 @@ struct X0 { }; void test_ctor_init() { (void)static_cast<X1>(X1()); } + +// Casting away constness +struct X2 { +}; + +struct X3 : X2 { +}; + +struct X4 { + typedef const X3 X3_typedef; + + void f() const { + (void)static_cast<X3_typedef*>(x2); + } + + const X2 *x2; +}; |