]> granicus.if.org Git - clang/commitdiff
When performing a static downcast as part of a static_cast, make sure
authorDouglas Gregor <dgregor@apple.com>
Sun, 15 Nov 2009 09:20:52 +0000 (09:20 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 15 Nov 2009 09:20:52 +0000 (09:20 +0000)
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

lib/Sema/SemaCXXCast.cpp
test/SemaCXX/static-cast.cpp

index d055dd4c58309c108d8ea1bb41172ac1060456f0..2ccad80bdc8c378cc7766e5894f583ac0ef123df 100644 (file)
@@ -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;
index 68f1dff276b881548f7ca9a5d853d1c45aa3d871..d3962727b806f83e38b8a7507ac52e1712d34981 100644 (file)
@@ -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;
+};