aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-11-15 09:20:52 +0000
committerDouglas Gregor <dgregor@apple.com>2009-11-15 09:20:52 +0000
commitab15d0e5af616c11b6cbb478c81d0a8eaa9d450a (patch)
tree6b0df8ec5feaff61900e216906516e88f7cdef18
parentc07a494b376f75f33759cf09ad188b11ef3fa9d5 (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.cpp29
-rw-r--r--test/SemaCXX/static-cast.cpp18
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;
+};