A few corrections to type traits that missed the last checkin

llvm-svn: 130371
This commit is contained in:
John Wiegley 2011-04-28 02:06:46 +00:00
parent 4c3b68c366
commit d352222839
2 changed files with 50 additions and 19 deletions

View File

@ -3335,6 +3335,10 @@ def warn_unused_call : Warning<
def err_incomplete_type_used_in_type_trait_expr : Error< def err_incomplete_type_used_in_type_trait_expr : Error<
"incomplete type %0 used in type trait expression">; "incomplete type %0 used in type trait expression">;
def err_dependent_type_used_in_type_trait_expr : Error<
"dependent type %0 used in type trait expression">;
def err_dimension_expr_not_constant_integer : Error<
"dimension expression does not evaluate to a constant unsigned int">;
def err_expected_ident_or_lparen : Error<"expected identifier or '('">; def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
def err_typecheck_cond_incompatible_operands_null : Error< def err_typecheck_cond_incompatible_operands_null : Error<

View File

@ -2355,8 +2355,12 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
SourceLocation KeyLoc) { SourceLocation KeyLoc) {
// FIXME: For many of these traits, we need a complete type before we can // FIXME: For many of these traits, we need a complete type before we can
// check these properties. // check these properties.
assert(!T->isDependentType() &&
"Cannot evaluate traits for dependent types."); if (T->isDependentType()) {
Self.Diag(KeyLoc, diag::err_dependent_type_used_in_type_trait_expr) << T;
return false;
}
ASTContext &C = Self.Context; ASTContext &C = Self.Context;
switch(UTT) { switch(UTT) {
default: assert(false && "Unknown type trait or not implemented"); default: assert(false && "Unknown type trait or not implemented");
@ -2653,7 +2657,16 @@ ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
QualType E = T; QualType E = T;
if (T->isIncompleteArrayType()) if (T->isIncompleteArrayType())
E = Context.getAsArrayType(T)->getElementType(); E = Context.getAsArrayType(T)->getElementType();
if (!T->isVoidType() && ! LangOpts.Borland && if (!T->isVoidType() &&
(! LangOpts.Borland ||
UTT == UTT_HasNothrowAssign ||
UTT == UTT_HasNothrowCopy ||
UTT == UTT_HasNothrowConstructor ||
UTT == UTT_HasTrivialAssign ||
UTT == UTT_HasTrivialCopy ||
UTT == UTT_HasTrivialConstructor ||
UTT == UTT_HasTrivialDestructor ||
UTT == UTT_HasVirtualDestructor) &&
RequireCompleteType(KWLoc, E, RequireCompleteType(KWLoc, E,
diag::err_incomplete_type_used_in_type_trait_expr)) diag::err_incomplete_type_used_in_type_trait_expr))
return ExprError(); return ExprError();
@ -2688,8 +2701,14 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
QualType LhsT, QualType RhsT, QualType LhsT, QualType RhsT,
SourceLocation KeyLoc) { SourceLocation KeyLoc) {
assert((!LhsT->isDependentType() || RhsT->isDependentType()) && if (LhsT->isDependentType()) {
"Cannot evaluate traits for dependent types."); Self.Diag(KeyLoc, diag::err_dependent_type_used_in_type_trait_expr) << LhsT;
return false;
}
else if (RhsT->isDependentType()) {
Self.Diag(KeyLoc, diag::err_dependent_type_used_in_type_trait_expr) << RhsT;
return false;
}
switch(BTT) { switch(BTT) {
case BTT_IsBaseOf: { case BTT_IsBaseOf: {
@ -2828,8 +2847,10 @@ ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT,
static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
QualType T, Expr *DimExpr, QualType T, Expr *DimExpr,
SourceLocation KeyLoc) { SourceLocation KeyLoc) {
assert((!T->isDependentType()) && if (T->isDependentType()) {
"Cannot evaluate traits for dependent types."); Self.Diag(KeyLoc, diag::err_dependent_type_used_in_type_trait_expr) << T;
return false;
}
switch(ATT) { switch(ATT) {
case ATT_ArrayRank: case ATT_ArrayRank:
@ -2840,16 +2861,24 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
T = AT->getElementType(); T = AT->getElementType();
} }
return Dim; return Dim;
} else {
assert(! "Array type trait applied to non-array type");
} }
return 0;
case ATT_ArrayExtent: { case ATT_ArrayExtent: {
llvm::APSInt Value; llvm::APSInt Value;
uint64_t Dim; uint64_t Dim;
if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) {
if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) {
Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) <<
DimExpr->getSourceRange();
return false;
}
Dim = Value.getLimitedValue(); Dim = Value.getLimitedValue();
else } else {
assert(! "Dimension expression did not evaluate to a constant integer"); Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) <<
DimExpr->getSourceRange();
return false;
}
if (T->isArrayType()) { if (T->isArrayType()) {
unsigned D = 0; unsigned D = 0;
@ -2863,14 +2892,12 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
T = AT->getElementType(); T = AT->getElementType();
} }
assert(Matched && T->isArrayType() && if (Matched && T->isArrayType()) {
"__array_extent does not refer to an array dimension"); if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T))
return CAT->getSize().getLimitedValue();
llvm::APInt size = Self.Context.getAsConstantArrayType(T)->getSize(); }
return size.getLimitedValue();
} else {
assert(! "Array type trait applied to non-array type");
} }
return 0;
} }
} }
llvm_unreachable("Unknown type trait or not implemented"); llvm_unreachable("Unknown type trait or not implemented");