aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp31
1 files changed, 23 insertions, 8 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 33d73bf106..b8d58c101c 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1929,18 +1929,33 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) {
} else if (castType->isDependentType() || castExpr->isTypeDependent()) {
// We can't check any more until template instantiation time.
} else if (!castType->isScalarType() && !castType->isVectorType()) {
- // GCC struct/union extension: allow cast to self.
- if (Context.getCanonicalType(castType).getUnqualifiedType() !=
- Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) ||
- (!castType->isStructureType() && !castType->isUnionType())) {
+ if (Context.getCanonicalType(castType).getUnqualifiedType() ==
+ Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) &&
+ (castType->isStructureType() || castType->isUnionType())) {
+ // GCC struct/union extension: allow cast to self.
+ Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
+ << castType << castExpr->getSourceRange();
+ } else if (castType->isUnionType()) {
+ // GCC cast to union extension
+ RecordDecl *RD = castType->getAsRecordType()->getDecl();
+ RecordDecl::field_iterator Field, FieldEnd;
+ for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Context.getCanonicalType(Field->getType()).getUnqualifiedType() ==
+ Context.getCanonicalType(castExpr->getType()).getUnqualifiedType()) {
+ Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union)
+ << castExpr->getSourceRange();
+ break;
+ }
+ }
+ if (Field == FieldEnd)
+ return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
+ << castExpr->getType() << castExpr->getSourceRange();
+ } else {
// Reject any other conversions to non-scalar types.
return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
<< castType << castExpr->getSourceRange();
}
-
- // accept this, but emit an ext-warn.
- Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
- << castType << castExpr->getSourceRange();
} else if (!castExpr->getType()->isScalarType() &&
!castExpr->getType()->isVectorType()) {
return Diag(castExpr->getLocStart(),