summaryrefslogtreecommitdiffstats
path: root/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
commit741c13ecc20fb35b836ad690aeecd402f002d654 (patch)
tree60a1694bec5a44d15456acc880cb2f91619f66aa /lib/Sema/Sema.cpp
parentb3a51061b1b9c4add078237850649f7c9efb13ab (diff)
downloadFreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.zip
FreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.tar.gz
Update clang to r89205.
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r--lib/Sema/Sema.cpp338
1 files changed, 328 insertions, 10 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 8104dd3..b2bbac8 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -14,6 +14,7 @@
#include "Sema.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/APFloat.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -346,16 +347,18 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- bool CompleteTranslationUnit)
+ bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CodeCompleter)
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
- ExternalSource(0), CodeCompleter(0), CurContext(0),
+ ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
- NumSFINAEErrors(0), CurrentInstantiationScope(0) {
-
+ NumSFINAEErrors(0), NonInstantiationEntries(0),
+ CurrentInstantiationScope(0)
+{
TUScope = 0;
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
@@ -364,6 +367,322 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context);
}
+/// Retrieves the width and signedness of the given integer type,
+/// or returns false if it is not an integer type.
+///
+/// \param T must be canonical
+static bool getIntProperties(ASTContext &C, const Type *T,
+ unsigned &BitWidth, bool &Signed) {
+ assert(T->isCanonicalUnqualified());
+
+ if (const VectorType *VT = dyn_cast<VectorType>(T))
+ T = VT->getElementType().getTypePtr();
+ if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+ T = CT->getElementType().getTypePtr();
+
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+ if (!BT->isInteger()) return false;
+
+ BitWidth = C.getIntWidth(QualType(T, 0));
+ Signed = BT->isSignedInteger();
+ return true;
+ }
+
+ if (const FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
+ BitWidth = FWIT->getWidth();
+ Signed = FWIT->isSigned();
+ return true;
+ }
+
+ return false;
+}
+
+/// Checks whether the given value will have the same value if it it
+/// is truncated to the given width, then extended back to the
+/// original width.
+static bool IsSameIntAfterCast(const llvm::APSInt &value,
+ unsigned TargetWidth) {
+ unsigned SourceWidth = value.getBitWidth();
+ llvm::APSInt truncated = value;
+ truncated.trunc(TargetWidth);
+ truncated.extend(SourceWidth);
+ return (truncated == value);
+}
+
+/// Checks whether the given value will have the same value if it
+/// is truncated to the given width, then extended back to the original
+/// width.
+///
+/// The value might be a vector or a complex.
+static bool IsSameIntAfterCast(const APValue &value, unsigned TargetWidth) {
+ if (value.isInt())
+ return IsSameIntAfterCast(value.getInt(), TargetWidth);
+
+ if (value.isVector()) {
+ for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+ if (!IsSameIntAfterCast(value.getVectorElt(i), TargetWidth))
+ return false;
+ return true;
+ }
+
+ if (value.isComplexInt()) {
+ return IsSameIntAfterCast(value.getComplexIntReal(), TargetWidth) &&
+ IsSameIntAfterCast(value.getComplexIntImag(), TargetWidth);
+ }
+
+ // This can happen with lossless casts to intptr_t of "based" lvalues.
+ // Assume it might use arbitrary bits.
+ assert(value.isLValue());
+ return false;
+}
+
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+static bool IsSameFloatAfterCast(const llvm::APFloat &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
+ llvm::APFloat truncated = value;
+
+ bool ignored;
+ truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
+ truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
+
+ return truncated.bitwiseIsEqual(value);
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+///
+/// The value might be a vector of floats (or a complex number).
+static bool IsSameFloatAfterCast(const APValue &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
+ if (value.isFloat())
+ return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
+
+ if (value.isVector()) {
+ for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+ if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
+ return false;
+ return true;
+ }
+
+ assert(value.isComplexFloat());
+ return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
+ IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
+}
+
+/// Determines if it's reasonable for the given expression to be truncated
+/// down to the given integer width.
+/// * Boolean expressions are automatically white-listed.
+/// * Arithmetic operations on implicitly-promoted operands of the
+/// target width or less are okay --- not because the results are
+/// actually guaranteed to fit within the width, but because the
+/// user is effectively pretending that the operations are closed
+/// within the implicitly-promoted type.
+static bool IsExprValueWithinWidth(ASTContext &C, Expr *E, unsigned Width) {
+ E = E->IgnoreParens();
+
+#ifndef NDEBUG
+ {
+ const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
+ unsigned EWidth;
+ bool ESigned;
+
+ if (!getIntProperties(C, ETy, EWidth, ESigned))
+ assert(0 && "expression not of integer type");
+
+ // The caller should never let this happen.
+ assert(EWidth > Width && "called on expr whose type is too small");
+ }
+#endif
+
+ // Strip implicit casts off.
+ while (isa<ImplicitCastExpr>(E)) {
+ E = cast<ImplicitCastExpr>(E)->getSubExpr();
+
+ const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
+
+ unsigned EWidth;
+ bool ESigned;
+ if (!getIntProperties(C, ETy, EWidth, ESigned))
+ return false;
+
+ if (EWidth <= Width)
+ return true;
+ }
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ switch (BO->getOpcode()) {
+
+ // Boolean-valued operations are white-listed.
+ case BinaryOperator::LAnd:
+ case BinaryOperator::LOr:
+ case BinaryOperator::LT:
+ case BinaryOperator::GT:
+ case BinaryOperator::LE:
+ case BinaryOperator::GE:
+ case BinaryOperator::EQ:
+ case BinaryOperator::NE:
+ return true;
+
+ // Operations with opaque sources are black-listed.
+ case BinaryOperator::PtrMemD:
+ case BinaryOperator::PtrMemI:
+ return false;
+
+ // Left shift gets black-listed based on a judgement call.
+ case BinaryOperator::Shl:
+ return false;
+
+ // Various special cases.
+ case BinaryOperator::Shr:
+ return IsExprValueWithinWidth(C, BO->getLHS(), Width);
+ case BinaryOperator::Comma:
+ return IsExprValueWithinWidth(C, BO->getRHS(), Width);
+ case BinaryOperator::Sub:
+ if (BO->getLHS()->getType()->isPointerType())
+ return false;
+ // fallthrough
+
+ // Any other operator is okay if the operands are
+ // promoted from expressions of appropriate size.
+ default:
+ return IsExprValueWithinWidth(C, BO->getLHS(), Width) &&
+ IsExprValueWithinWidth(C, BO->getRHS(), Width);
+ }
+ }
+
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ switch (UO->getOpcode()) {
+ // Boolean-valued operations are white-listed.
+ case UnaryOperator::LNot:
+ return true;
+
+ // Operations with opaque sources are black-listed.
+ case UnaryOperator::Deref:
+ case UnaryOperator::AddrOf: // should be impossible
+ return false;
+
+ case UnaryOperator::OffsetOf:
+ return false;
+
+ default:
+ return IsExprValueWithinWidth(C, UO->getSubExpr(), Width);
+ }
+ }
+
+ // Don't diagnose if the expression is an integer constant
+ // whose value in the target type is the same as it was
+ // in the original type.
+ Expr::EvalResult result;
+ if (E->Evaluate(result, C))
+ if (IsSameIntAfterCast(result.Val, Width))
+ return true;
+
+ return false;
+}
+
+/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
+ S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
+}
+
+/// Implements -Wconversion.
+static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) {
+ // Don't diagnose in unevaluated contexts.
+ if (S.ExprEvalContext == Sema::Unevaluated)
+ return;
+
+ // Don't diagnose for value-dependent expressions.
+ if (E->isValueDependent())
+ return;
+
+ const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
+ const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
+
+ // Never diagnose implicit casts to bool.
+ if (Target->isSpecificBuiltinType(BuiltinType::Bool))
+ return;
+
+ // Strip vector types.
+ if (isa<VectorType>(Source)) {
+ if (!isa<VectorType>(Target))
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_vector_scalar);
+
+ Source = cast<VectorType>(Source)->getElementType().getTypePtr();
+ Target = cast<VectorType>(Target)->getElementType().getTypePtr();
+ }
+
+ // Strip complex types.
+ if (isa<ComplexType>(Source)) {
+ if (!isa<ComplexType>(Target))
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_complex_scalar);
+
+ Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
+ Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
+ }
+
+ const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
+ const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
+
+ // If the source is floating point...
+ if (SourceBT && SourceBT->isFloatingPoint()) {
+ // ...and the target is floating point...
+ if (TargetBT && TargetBT->isFloatingPoint()) {
+ // ...then warn if we're dropping FP rank.
+
+ // Builtin FP kinds are ordered by increasing FP rank.
+ if (SourceBT->getKind() > TargetBT->getKind()) {
+ // Don't warn about float constants that are precisely
+ // representable in the target type.
+ Expr::EvalResult result;
+ if (E->Evaluate(result, S.Context)) {
+ // Value might be a float, a float vector, or a float complex.
+ if (IsSameFloatAfterCast(result.Val,
+ S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
+ S.Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
+ return;
+ }
+
+ DiagnoseImpCast(S, E, T, diag::warn_impcast_float_precision);
+ }
+ return;
+ }
+
+ // If the target is integral, always warn.
+ if ((TargetBT && TargetBT->isInteger()) ||
+ isa<FixedWidthIntType>(Target))
+ // TODO: don't warn for integer values?
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_float_integer);
+
+ return;
+ }
+
+ unsigned SourceWidth, TargetWidth;
+ bool SourceSigned, TargetSigned;
+
+ if (!getIntProperties(S.Context, Source, SourceWidth, SourceSigned) ||
+ !getIntProperties(S.Context, Target, TargetWidth, TargetSigned))
+ return;
+
+ if (SourceWidth > TargetWidth) {
+ if (IsExprValueWithinWidth(S.Context, E, TargetWidth))
+ return;
+
+ // People want to build with -Wshorten-64-to-32 and not -Wconversion
+ // and by god we'll let them.
+ if (SourceWidth == 64 && TargetWidth == 32)
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_64_32);
+ return DiagnoseImpCast(S, E, T, diag::warn_impcast_integer_precision);
+ }
+
+ return;
+}
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
@@ -375,18 +694,17 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
if (ExprTy == TypeTy)
return;
- if (Expr->getType().getTypePtr()->isPointerType() &&
- Ty.getTypePtr()->isPointerType()) {
- QualType ExprBaseType =
- cast<PointerType>(ExprTy.getUnqualifiedType())->getPointeeType();
- QualType BaseType =
- cast<PointerType>(TypeTy.getUnqualifiedType())->getPointeeType();
+ if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
+ QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
+ QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
<< Expr->getSourceRange();
}
}
+ CheckImplicitConversion(*this, Expr, Ty);
+
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
if (ImpCast->getCastKind() == Kind) {
ImpCast->setType(Ty);
OpenPOWER on IntegriCloud