diff options
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 31 |
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(), |