summaryrefslogtreecommitdiffstats
path: root/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r--lib/Sema/Sema.cpp322
1 files changed, 13 insertions, 309 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 40ad90a..171101b 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "TargetAttributesSema.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/APFloat.h"
#include "clang/AST/ASTConsumer.h"
@@ -109,6 +110,12 @@ static bool ShouldAKA(ASTContext &Context, QualType QT,
if (isa<VectorType>(Underlying))
break;
+ // Don't desugar through the primary typedef of an anonymous type.
+ if (isa<TagType>(Underlying) && isa<TypedefType>(QT))
+ if (cast<TagType>(Underlying)->getDecl()->getTypedefForAnonDecl() ==
+ cast<TypedefType>(QT)->getDecl())
+ break;
+
// Otherwise, we're tearing through something opaque; note that
// we'll eventually need an a.k.a. clause and keep going.
AKA = true;
@@ -347,7 +354,8 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
bool CompleteTranslationUnit,
CodeCompleteConsumer *CodeCompleter)
- : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
+ : TheTargetAttributesSema(0),
+ LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
CurBlock(0), PackContext(0), ParsingDeclDepth(0),
@@ -368,313 +376,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
}
-/// 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;
- }
-
- 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.ExprEvalContexts.back().Context == 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()))
- // 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;
+Sema::~Sema() {
+ if (PackContext) FreePackedContext();
+ delete TheTargetAttributesSema;
}
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
@@ -697,7 +401,7 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
}
}
- CheckImplicitConversion(*this, Expr, Ty);
+ CheckImplicitConversion(Expr, Ty);
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
if (ImpCast->getCastKind() == Kind) {
OpenPOWER on IntegriCloud