diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp | 1963 |
1 files changed, 1426 insertions, 537 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 0530a04..420aff3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -27,14 +27,14 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/raw_ostream.h" #include <limits> @@ -43,8 +43,8 @@ using namespace sema; SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, unsigned ByteNo) const { - return SL->getLocationOfByte(ByteNo, PP.getSourceManager(), - PP.getLangOpts(), PP.getTargetInfo()); + return SL->getLocationOfByte(ByteNo, getSourceManager(), LangOpts, + Context.getTargetInfo()); } /// Checks that a call expression's argument count is the desired number. @@ -101,19 +101,19 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) { if (checkArgCount(S, TheCall, 1)) return true; - ExprResult Arg(S.Owned(TheCall->getArg(0))); + ExprResult Arg(TheCall->getArg(0)); QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart()); if (ResultType.isNull()) return true; - TheCall->setArg(0, Arg.take()); + TheCall->setArg(0, Arg.get()); TheCall->setType(ResultType); return false; } ExprResult Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - ExprResult TheCallResult(Owned(TheCall)); + ExprResult TheCallResult(TheCall); // Find out if any arguments are required to be integer constant expressions. unsigned ICEArguments = 0; @@ -145,6 +145,20 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinVAStart(TheCall)) return ExprError(); break; + case Builtin::BI__va_start: { + switch (Context.getTargetInfo().getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (SemaBuiltinVAStartARM(TheCall)) + return ExprError(); + break; + default: + if (SemaBuiltinVAStart(TheCall)) + return ExprError(); + break; + } + break; + } case Builtin::BI__builtin_isgreater: case Builtin::BI__builtin_isgreaterequal: case Builtin::BI__builtin_isless: @@ -174,8 +188,12 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinPrefetch(TheCall)) return ExprError(); break; + case Builtin::BI__assume: + if (SemaBuiltinAssume(TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_object_size: - if (SemaBuiltinObjectSize(TheCall)) + if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) return ExprError(); break; case Builtin::BI__builtin_longjmp: @@ -295,18 +313,37 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinAddressof(*this, TheCall)) return ExprError(); break; + case Builtin::BI__builtin_operator_new: + case Builtin::BI__builtin_operator_delete: + if (!getLangOpts().CPlusPlus) { + Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language) + << (BuiltinID == Builtin::BI__builtin_operator_new + ? "__builtin_operator_new" + : "__builtin_operator_delete") + << "C++"; + return ExprError(); + } + // CodeGen assumes it can find the global new and delete to call, + // so ensure that they are declared. + DeclareGlobalNewDelete(); + break; } - + // Since the target specific builtins for each arch overlap, only check those // of the arch we are compiling for. if (BuiltinID >= Builtin::FirstTSBuiltin) { switch (Context.getTargetInfo().getTriple().getArch()) { case llvm::Triple::arm: + case llvm::Triple::armeb: case llvm::Triple::thumb: + case llvm::Triple::thumbeb: if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm64: + case llvm::Triple::arm64_be: if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; @@ -317,6 +354,11 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; default: break; } @@ -326,9 +368,9 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } // Get the valid immediate range for the specified NEON type code. -static unsigned RFT(unsigned t, bool shift = false) { +static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) { NeonTypeFlags Type(t); - int IsQuad = Type.isQuad(); + int IsQuad = ForceQuad ? true : Type.isQuad(); switch (Type.getEltType()) { case NeonTypeFlags::Int8: case NeonTypeFlags::Poly8: @@ -341,6 +383,8 @@ static unsigned RFT(unsigned t, bool shift = false) { case NeonTypeFlags::Int64: case NeonTypeFlags::Poly64: return shift ? 63 : (1 << IsQuad) - 1; + case NeonTypeFlags::Poly128: + return shift ? 127 : (1 << IsQuad) - 1; case NeonTypeFlags::Float16: assert(!shift && "cannot shift float types!"); return (4 << IsQuad) - 1; @@ -358,7 +402,7 @@ static unsigned RFT(unsigned t, bool shift = false) { /// the vector type specified by the NeonTypeFlags. This is used to check /// the pointer arguments for Neon load/store intrinsics. static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, - bool IsAArch64) { + bool IsPolyUnsigned, bool IsInt64Long) { switch (Flags.getEltType()) { case NeonTypeFlags::Int8: return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy; @@ -367,13 +411,19 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, case NeonTypeFlags::Int32: return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy; case NeonTypeFlags::Int64: - return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy; + if (IsInt64Long) + return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy; + else + return Flags.isUnsigned() ? Context.UnsignedLongLongTy + : Context.LongLongTy; case NeonTypeFlags::Poly8: - return IsAArch64 ? Context.UnsignedCharTy : Context.SignedCharTy; + return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy; case NeonTypeFlags::Poly16: - return IsAArch64 ? Context.UnsignedShortTy : Context.ShortTy; + return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy; case NeonTypeFlags::Poly64: - return Context.UnsignedLongLongTy; + return Context.UnsignedLongTy; + case NeonTypeFlags::Poly128: + break; case NeonTypeFlags::Float16: return Context.HalfTy; case NeonTypeFlags::Float32: @@ -384,24 +434,21 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, llvm_unreachable("Invalid NeonTypeFlag!"); } -bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, - CallExpr *TheCall) { - +bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { llvm::APSInt Result; - uint64_t mask = 0; unsigned TV = 0; int PtrArgNum = -1; bool HasConstPtr = false; switch (BuiltinID) { -#define GET_NEON_AARCH64_OVERLOAD_CHECK +#define GET_NEON_OVERLOAD_CHECK #include "clang/Basic/arm_neon.inc" -#undef GET_NEON_AARCH64_OVERLOAD_CHECK +#undef GET_NEON_OVERLOAD_CHECK } // For NEON intrinsics which are overloaded on vector element type, validate // the immediate which specifies which variant to emit. - unsigned ImmArg = TheCall->getNumArgs() - 1; + unsigned ImmArg = TheCall->getNumArgs()-1; if (mask) { if (SemaBuiltinConstantArg(TheCall, ImmArg, Result)) return true; @@ -409,7 +456,7 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, TV = Result.getLimitedValue(64); if ((TV > 63) || (mask & (1ULL << TV)) == 0) return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) - << TheCall->getArg(ImmArg)->getSourceRange(); + << TheCall->getArg(ImmArg)->getSourceRange(); } if (PtrArgNum >= 0) { @@ -419,7 +466,14 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, Arg = ICE->getSubExpr(); ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg); QualType RHSTy = RHS.get()->getType(); - QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, true); + + llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); + bool IsPolyUnsigned = + Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::arm64; + bool IsInt64Long = + Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong; + QualType EltTy = + getNeonEltType(NeonTypeFlags(TV), Context, IsPolyUnsigned, IsInt64Long); if (HasConstPtr) EltTy = EltTy.withConst(); QualType LHSTy = Context.getPointerType(EltTy); @@ -438,35 +492,29 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, switch (BuiltinID) { default: return false; -#define GET_NEON_AARCH64_IMMEDIATE_CHECK +#define GET_NEON_IMMEDIATE_CHECK #include "clang/Basic/arm_neon.inc" -#undef GET_NEON_AARCH64_IMMEDIATE_CHECK +#undef GET_NEON_IMMEDIATE_CHECK } - ; - // We can't check the value of a dependent argument. - if (TheCall->getArg(i)->isTypeDependent() || - TheCall->getArg(i)->isValueDependent()) - return false; - - // Check that the immediate argument is actually a constant. - if (SemaBuiltinConstantArg(TheCall, i, Result)) - return true; - - // Range check against the upper/lower values for this isntruction. - unsigned Val = Result.getZExtValue(); - if (Val < l || Val > (u + l)) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << l << u + l << TheCall->getArg(i)->getSourceRange(); - - return false; + return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); } -bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) { +bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, + unsigned MaxWidth) { assert((BuiltinID == ARM::BI__builtin_arm_ldrex || - BuiltinID == ARM::BI__builtin_arm_strex) && + BuiltinID == ARM::BI__builtin_arm_ldaex || + BuiltinID == ARM::BI__builtin_arm_strex || + BuiltinID == ARM::BI__builtin_arm_stlex || + BuiltinID == AArch64::BI__builtin_arm_ldrex || + BuiltinID == AArch64::BI__builtin_arm_ldaex || + BuiltinID == AArch64::BI__builtin_arm_strex || + BuiltinID == AArch64::BI__builtin_arm_stlex) && "unexpected ARM builtin"); - bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex; + bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex || + BuiltinID == ARM::BI__builtin_arm_ldaex || + BuiltinID == AArch64::BI__builtin_arm_ldrex || + BuiltinID == AArch64::BI__builtin_arm_ldaex; DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); @@ -482,7 +530,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) { ExprResult PointerArgRes = DefaultFunctionArrayLvalueConversion(PointerArg); if (PointerArgRes.isInvalid()) return true; - PointerArg = PointerArgRes.take(); + PointerArg = PointerArgRes.get(); const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); if (!pointerType) { @@ -514,7 +562,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) { PointerArgRes = ImpCastExprToType(PointerArg, AddrType, CastNeeded); if (PointerArgRes.isInvalid()) return true; - PointerArg = PointerArgRes.take(); + PointerArg = PointerArgRes.get(); TheCall->setArg(IsLdrex ? 0 : 1, PointerArg); @@ -527,7 +575,8 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) { } // But ARM doesn't have instructions to deal with 128-bit versions. - if (Context.getTypeSize(ValType) > 64) { + if (Context.getTypeSize(ValType) > MaxWidth) { + assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate"); Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size) << PointerArg->getType() << PointerArg->getSourceRange(); return true; @@ -572,55 +621,17 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { llvm::APSInt Result; if (BuiltinID == ARM::BI__builtin_arm_ldrex || - BuiltinID == ARM::BI__builtin_arm_strex) { - return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall); + BuiltinID == ARM::BI__builtin_arm_ldaex || + BuiltinID == ARM::BI__builtin_arm_strex || + BuiltinID == ARM::BI__builtin_arm_stlex) { + return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64); } - uint64_t mask = 0; - unsigned TV = 0; - int PtrArgNum = -1; - bool HasConstPtr = false; - switch (BuiltinID) { -#define GET_NEON_OVERLOAD_CHECK -#include "clang/Basic/arm_neon.inc" -#undef GET_NEON_OVERLOAD_CHECK - } - - // For NEON intrinsics which are overloaded on vector element type, validate - // the immediate which specifies which variant to emit. - unsigned ImmArg = TheCall->getNumArgs()-1; - if (mask) { - if (SemaBuiltinConstantArg(TheCall, ImmArg, Result)) - return true; - - TV = Result.getLimitedValue(64); - if ((TV > 63) || (mask & (1ULL << TV)) == 0) - return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) - << TheCall->getArg(ImmArg)->getSourceRange(); - } + if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall)) + return true; - if (PtrArgNum >= 0) { - // Check that pointer arguments have the specified type. - Expr *Arg = TheCall->getArg(PtrArgNum); - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) - Arg = ICE->getSubExpr(); - ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg); - QualType RHSTy = RHS.get()->getType(); - QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, false); - if (HasConstPtr) - EltTy = EltTy.withConst(); - QualType LHSTy = Context.getPointerType(EltTy); - AssignConvertType ConvTy; - ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); - if (RHS.isInvalid()) - return true; - if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy, - RHS.get(), AA_Assigning)) - return true; - } - - // For NEON intrinsics which take an immediate value as part of the - // instruction, range check them here. + // For intrinsics which take an immediate value as part of the instruction, + // range check them here. unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; @@ -629,29 +640,40 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case ARM::BI__builtin_arm_vcvtr_f: case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break; case ARM::BI__builtin_arm_dmb: - case ARM::BI__builtin_arm_dsb: l = 0; u = 15; break; -#define GET_NEON_IMMEDIATE_CHECK -#include "clang/Basic/arm_neon.inc" -#undef GET_NEON_IMMEDIATE_CHECK - }; + case ARM::BI__builtin_arm_dsb: + case ARM::BI__builtin_arm_isb: l = 0; u = 15; break; + } - // We can't check the value of a dependent argument. - if (TheCall->getArg(i)->isTypeDependent() || - TheCall->getArg(i)->isValueDependent()) - return false; + // FIXME: VFP Intrinsics should error if VFP not present. + return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); +} + +bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + llvm::APSInt Result; + + if (BuiltinID == AArch64::BI__builtin_arm_ldrex || + BuiltinID == AArch64::BI__builtin_arm_ldaex || + BuiltinID == AArch64::BI__builtin_arm_strex || + BuiltinID == AArch64::BI__builtin_arm_stlex) { + return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128); + } - // Check that the immediate argument is actually a constant. - if (SemaBuiltinConstantArg(TheCall, i, Result)) + if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall)) return true; - // Range check against the upper/lower values for this isntruction. - unsigned Val = Result.getZExtValue(); - if (Val < l || Val > (u + l)) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << l << u+l << TheCall->getArg(i)->getSourceRange(); + // For intrinsics which take an immediate value as part of the instruction, + // range check them here. + unsigned i = 0, l = 0, u = 0; + switch (BuiltinID) { + default: return false; + case AArch64::BI__builtin_arm_dmb: + case AArch64::BI__builtin_arm_dsb: + case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break; + } // FIXME: VFP Intrinsics should error if VFP not present. - return false; + return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); } bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { @@ -665,24 +687,17 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break; case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break; case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break; - }; - - // We can't check the value of a dependent argument. - if (TheCall->getArg(i)->isTypeDependent() || - TheCall->getArg(i)->isValueDependent()) - return false; - - // Check that the immediate argument is actually a constant. - llvm::APSInt Result; - if (SemaBuiltinConstantArg(TheCall, i, Result)) - return true; + } - // Range check against the upper/lower values for this instruction. - unsigned Val = Result.getZExtValue(); - if (Val < l || Val > u) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << l << u << TheCall->getArg(i)->getSourceRange(); + return SemaBuiltinConstantArgRange(TheCall, i, l, u); +} +bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + switch (BuiltinID) { + case X86::BI_mm_prefetch: + // This is declared to take (const char*, int) + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3); + } return false; } @@ -709,14 +724,66 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, return true; } +/// Checks if a the given expression evaluates to null. +/// +/// \brief Returns true if the value evaluates to null. +static bool CheckNonNullExpr(Sema &S, + const Expr *Expr) { + // As a special case, transparent unions initialized with zero are + // considered null for the purposes of the nonnull attribute. + if (const RecordType *UT = Expr->getType()->getAsUnionType()) { + if (UT->getDecl()->hasAttr<TransparentUnionAttr>()) + if (const CompoundLiteralExpr *CLE = + dyn_cast<CompoundLiteralExpr>(Expr)) + if (const InitListExpr *ILE = + dyn_cast<InitListExpr>(CLE->getInitializer())) + Expr = ILE->getInit(0); + } + + bool Result; + return (!Expr->isValueDependent() && + Expr->EvaluateAsBooleanCondition(Result, S.Context) && + !Result); +} + +static void CheckNonNullArgument(Sema &S, + const Expr *ArgExpr, + SourceLocation CallSiteLoc) { + if (CheckNonNullExpr(S, ArgExpr)) + S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); +} + +static void CheckNonNullArguments(Sema &S, + const NamedDecl *FDecl, + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc) { + // Check the attributes attached to the method/function itself. + for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) { + for (const auto &Val : NonNull->args()) + CheckNonNullArgument(S, ExprArgs[Val], CallSiteLoc); + } + + // Check the attributes on the parameters. + ArrayRef<ParmVarDecl*> parms; + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl)) + parms = FD->parameters(); + else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl)) + parms = MD->parameters(); + + unsigned argIndex = 0; + for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end(); + I != E; ++I, ++argIndex) { + const ParmVarDecl *PVD = *I; + if (PVD->hasAttr<NonNullAttr>()) + CheckNonNullArgument(S, ExprArgs[argIndex], CallSiteLoc); + } +} + /// Handles the checks for format strings, non-POD arguments to vararg /// functions, and NULL arguments passed to non-NULL parameters. -void Sema::checkCall(NamedDecl *FDecl, - ArrayRef<const Expr *> Args, - unsigned NumProtoArgs, - bool IsMemberFunction, - SourceLocation Loc, - SourceRange Range, +void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args, + unsigned NumParams, bool IsMemberFunction, + SourceLocation Loc, SourceRange Range, VariadicCallType CallType) { // FIXME: We should check as much as we can in the template definition. if (CurContext->isDependentContext()) @@ -725,14 +792,11 @@ void Sema::checkCall(NamedDecl *FDecl, // Printf and scanf checking. llvm::SmallBitVector CheckedVarArgs; if (FDecl) { - for (specific_attr_iterator<FormatAttr> - I = FDecl->specific_attr_begin<FormatAttr>(), - E = FDecl->specific_attr_end<FormatAttr>(); - I != E; ++I) { + for (const auto *I : FDecl->specific_attrs<FormatAttr>()) { // Only create vector if there are format attributes. CheckedVarArgs.resize(Args.size()); - CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range, + CheckFormatArguments(I, Args, IsMemberFunction, CallType, Loc, Range, CheckedVarArgs); } } @@ -740,7 +804,7 @@ void Sema::checkCall(NamedDecl *FDecl, // Refuse POD arguments that weren't caught by the format string // checks above. if (CallType != VariadicDoesNotApply) { - for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) { + for (unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. if (const Expr *Arg = Args[ArgIdx]) { if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx]) @@ -750,18 +814,11 @@ void Sema::checkCall(NamedDecl *FDecl, } if (FDecl) { - for (specific_attr_iterator<NonNullAttr> - I = FDecl->specific_attr_begin<NonNullAttr>(), - E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) - CheckNonNullArguments(*I, Args.data(), Loc); + CheckNonNullArguments(*this, FDecl, Args.data(), Loc); // Type safety checking. - for (specific_attr_iterator<ArgumentWithTypeTagAttr> - i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(), - e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); - i != e; ++i) { - CheckArgumentWithTypeTag(*i, Args.data()); - } + for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>()) + CheckArgumentWithTypeTag(I, Args.data()); } } @@ -773,7 +830,7 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl, SourceLocation Loc) { VariadicCallType CallType = Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; - checkCall(FDecl, Args, Proto->getNumArgs(), + checkCall(FDecl, Args, Proto->getNumParams(), /*IsMemberFunction=*/true, Loc, SourceRange(), CallType); } @@ -787,7 +844,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, IsMemberOperatorCall; VariadicCallType CallType = getVariadicCallType(FDecl, Proto, TheCall->getCallee()); - unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; + unsigned NumParams = Proto ? Proto->getNumParams() : 0; Expr** Args = TheCall->getArgs(); unsigned NumArgs = TheCall->getNumArgs(); if (IsMemberOperatorCall) { @@ -797,8 +854,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, ++Args; --NumArgs; } - checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs), - NumProtoArgs, + checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs), NumParams, IsMemberFunction, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -808,6 +864,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, if (!FnInfo) return false; + CheckAbsoluteValueFunction(TheCall, FDecl, FnInfo); + unsigned CMId = FDecl->getMemoryFunctionKind(); if (CMId == 0) return false; @@ -853,35 +911,59 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, } else { // Ty->isFunctionPointerType() CallType = VariadicFunction; } - unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; + unsigned NumParams = Proto ? Proto->getNumParams() : 0; - checkCall(NDecl, - llvm::makeArrayRef<const Expr *>(TheCall->getArgs(), - TheCall->getNumArgs()), - NumProtoArgs, /*IsMemberFunction=*/false, - TheCall->getRParenLoc(), + checkCall(NDecl, llvm::makeArrayRef<const Expr *>(TheCall->getArgs(), + TheCall->getNumArgs()), + NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); - + return false; } /// Checks function calls when a FunctionDecl or a NamedDecl is not available, /// such as function pointers returned from functions. bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { - VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto, + VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto, TheCall->getCallee()); - unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; + unsigned NumParams = Proto ? Proto->getNumParams() : 0; - checkCall(/*FDecl=*/0, + checkCall(/*FDecl=*/nullptr, llvm::makeArrayRef<const Expr *>(TheCall->getArgs(), TheCall->getNumArgs()), - NumProtoArgs, /*IsMemberFunction=*/false, - TheCall->getRParenLoc(), + NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); return false; } +static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { + if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed || + Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst) + return false; + + switch (Op) { + case AtomicExpr::AO__c11_atomic_init: + llvm_unreachable("There is no ordering argument for an init"); + + case AtomicExpr::AO__c11_atomic_load: + case AtomicExpr::AO__atomic_load_n: + case AtomicExpr::AO__atomic_load: + return Ordering != AtomicExpr::AO_ABI_memory_order_release && + Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + + case AtomicExpr::AO__c11_atomic_store: + case AtomicExpr::AO__atomic_store: + case AtomicExpr::AO__atomic_store_n: + return Ordering != AtomicExpr::AO_ABI_memory_order_consume && + Ordering != AtomicExpr::AO_ABI_memory_order_acquire && + Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + + default: + return true; + } +} + ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) { CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); @@ -1170,7 +1252,16 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, SubExprs.push_back(TheCall->getArg(3)); // Weak break; } - + + if (SubExprs.size() >= 2 && Form != Init) { + llvm::APSInt Result(32); + if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && + !isValidOrderingForOp(Result.getSExtValue(), Op)) + Diag(SubExprs[1]->getLocStart(), + diag::warn_atomic_op_has_invalid_memory_order) + << SubExprs[1]->getSourceRange(); + } + AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), SubExprs, ResultType, Op, TheCall->getRParenLoc()); @@ -1181,7 +1272,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib) << ((Op == AtomicExpr::AO__c11_atomic_load) ? 0 : 1); - return Owned(AE); + return AE; } @@ -1205,7 +1296,7 @@ static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) { if (Arg.isInvalid()) return true; - E->setArg(ArgIndex, Arg.take()); + E->setArg(ArgIndex, Arg.get()); return false; } @@ -1240,7 +1331,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg); if (FirstArgResult.isInvalid()) return ExprError(); - FirstArg = FirstArgResult.take(); + FirstArg = FirstArgResult.get(); TheCall->setArg(0, FirstArg); const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>(); @@ -1493,7 +1584,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true); assert(Res.getFoundDecl()); NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl()); - if (NewBuiltinDecl == 0) + if (!NewBuiltinDecl) return ExprError(); } @@ -1518,7 +1609,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // pass in 42. The 42 gets converted to char. This is even more strange // for things like 45.123 -> char, etc. // FIXME: Do this check. - TheCall->setArg(i+1, Arg.take()); + TheCall->setArg(i+1, Arg.get()); } ASTContext& Context = this->getASTContext(); @@ -1539,7 +1630,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { QualType CalleePtrTy = Context.getPointerType(NewBuiltinDecl->getType()); ExprResult PromotedCall = ImpCastExprToType(NewDRE, CalleePtrTy, CK_BuiltinFnToFnPtr); - TheCall->setCallee(PromotedCall.take()); + TheCall->setCallee(PromotedCall.get()); // Change the result type of the call to match the original value type. This // is arbitrary, but the codegen for these builtins ins design to handle it @@ -1661,6 +1752,58 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { return false; } +bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) { + // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, + // const char *named_addr); + + Expr *Func = Call->getCallee(); + + if (Call->getNumArgs() < 3) + return Diag(Call->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 3 << Call->getNumArgs(); + + // Determine whether the current function is variadic or not. + bool IsVariadic; + if (BlockScopeInfo *CurBlock = getCurBlock()) + IsVariadic = CurBlock->TheDecl->isVariadic(); + else if (FunctionDecl *FD = getCurFunctionDecl()) + IsVariadic = FD->isVariadic(); + else if (ObjCMethodDecl *MD = getCurMethodDecl()) + IsVariadic = MD->isVariadic(); + else + llvm_unreachable("unexpected statement type"); + + if (!IsVariadic) { + Diag(Func->getLocStart(), diag::err_va_start_used_in_non_variadic_function); + return true; + } + + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, Call, 0)) + return true; + + static const struct { + unsigned ArgNo; + QualType Type; + } ArgumentTypes[] = { + { 1, Context.getPointerType(Context.CharTy.withConst()) }, + { 2, Context.getSizeType() }, + }; + + for (const auto &AT : ArgumentTypes) { + const Expr *Arg = Call->getArg(AT.ArgNo)->IgnoreParens(); + if (Arg->getType().getCanonicalType() == AT.Type.getCanonicalType()) + continue; + Diag(Arg->getLocStart(), diag::err_typecheck_convert_incompatible) + << Arg->getType() << AT.Type << 1 /* different class */ + << 0 /* qualifier difference */ << 3 /* parameter mismatch */ + << AT.ArgNo + 1 << Arg->getType() << AT.Type; + } + + return false; +} + /// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and /// friends. This is declared to take (...), so we have to check everything. bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { @@ -1735,7 +1878,7 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && "promotion from float to double is the only expected cast here"); - Cast->setSubExpr(0); + Cast->setSubExpr(nullptr); TheCall->setArg(NumArgs-1, CastArg); } } @@ -1820,12 +1963,12 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { exprs.push_back(TheCall->getArg(i)); - TheCall->setArg(i, 0); + TheCall->setArg(i, nullptr); } - return Owned(new (Context) ShuffleVectorExpr(Context, exprs, resType, - TheCall->getCallee()->getLocStart(), - TheCall->getRParenLoc())); + return new (Context) ShuffleVectorExpr(Context, exprs, resType, + TheCall->getCallee()->getLocStart(), + TheCall->getRParenLoc()); } /// SemaConvertVectorExpr - Handle __builtin_convertvector @@ -1854,9 +1997,8 @@ ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, << E->getSourceRange()); } - return Owned(new (Context) ConvertVectorExpr(E, TInfo, DstTy, VK, OK, - BuiltinLoc, RParenLoc)); - + return new (Context) + ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc); } /// SemaBuiltinPrefetch - Handle __builtin_prefetch. @@ -1873,30 +2015,23 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { // Argument 0 is checked for us and the remaining arguments must be // constant integers. - for (unsigned i = 1; i != NumArgs; ++i) { - Expr *Arg = TheCall->getArg(i); + for (unsigned i = 1; i != NumArgs; ++i) + if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3)) + return true; - // We can't check the value of a dependent argument. - if (Arg->isTypeDependent() || Arg->isValueDependent()) - continue; + return false; +} - llvm::APSInt Result; - if (SemaBuiltinConstantArg(TheCall, i, Result)) - return true; +/// SemaBuiltinAssume - Handle __assume (MS Extension). +// __assume does not evaluate its arguments, and should warn if its argument +// has side effects. +bool Sema::SemaBuiltinAssume(CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(0); + if (Arg->isInstantiationDependent()) return false; - // FIXME: gcc issues a warning and rewrites these to 0. These - // seems especially odd for the third argument since the default - // is 3. - if (i == 1) { - if (Result.getLimitedValue() > 1) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << "0" << "1" << Arg->getSourceRange(); - } else { - if (Result.getLimitedValue() > 3) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << "0" << "3" << Arg->getSourceRange(); - } - } + if (Arg->HasSideEffects(Context)) + return Diag(Arg->getLocStart(), diag::warn_assume_side_effects) + << Arg->getSourceRange(); return false; } @@ -1918,27 +2053,24 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, return false; } -/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, -/// int type). This simply type checks that type is one of the defined -/// constants (0-3). -// For compatibility check 0-3, llvm only handles 0 and 2. -bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { +/// SemaBuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr +/// TheCall is a constant expression in the range [Low, High]. +bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, + int Low, int High) { llvm::APSInt Result; // We can't check the value of a dependent argument. - if (TheCall->getArg(1)->isTypeDependent() || - TheCall->getArg(1)->isValueDependent()) + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; // Check constant-ness first. - if (SemaBuiltinConstantArg(TheCall, 1, Result)) + if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) return true; - Expr *Arg = TheCall->getArg(1); - if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) { + if (Result.getSExtValue() < Low || Result.getSExtValue() > High) return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); - } + << Low << High << Arg->getSourceRange(); return false; } @@ -2081,10 +2213,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) { if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) { int PVIndex = PV->getFunctionScopeIndex() + 1; - for (specific_attr_iterator<FormatAttr> - i = ND->specific_attr_begin<FormatAttr>(), - e = ND->specific_attr_end<FormatAttr>(); i != e ; ++i) { - FormatAttr *PVFormat = *i; + for (const auto *PVFormat : ND->specific_attrs<FormatAttr>()) { // adjust for implicit parameter if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) if (MD->isInstance()) @@ -2133,30 +2262,9 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, return SLCT_NotALiteral; } - - case Stmt::ObjCMessageExprClass: { - const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(E); - if (const ObjCMethodDecl *MDecl = ME->getMethodDecl()) { - if (const NamedDecl *ND = dyn_cast<NamedDecl>(MDecl)) { - if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) { - unsigned ArgIndex = FA->getFormatIdx(); - if (ArgIndex <= ME->getNumArgs()) { - const Expr *Arg = ME->getArg(ArgIndex-1); - return checkFormatStringExpr(S, Arg, Args, - HasVAListArg, format_idx, - firstDataArg, Type, CallType, - InFunctionCall, CheckedVarArgs); - } - } - } - } - - return SLCT_NotALiteral; - } - case Stmt::ObjCStringLiteralClass: case Stmt::StringLiteralClass: { - const StringLiteral *StrE = NULL; + const StringLiteral *StrE = nullptr; if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E)) StrE = ObjCFExpr->getString(); @@ -2177,32 +2285,6 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, } } -void -Sema::CheckNonNullArguments(const NonNullAttr *NonNull, - const Expr * const *ExprArgs, - SourceLocation CallSiteLoc) { - for (NonNullAttr::args_iterator i = NonNull->args_begin(), - e = NonNull->args_end(); - i != e; ++i) { - const Expr *ArgExpr = ExprArgs[*i]; - - // As a special case, transparent unions initialized with zero are - // considered null for the purposes of the nonnull attribute. - if (const RecordType *UT = ArgExpr->getType()->getAsUnionType()) { - if (UT->getDecl()->hasAttr<TransparentUnionAttr>()) - if (const CompoundLiteralExpr *CLE = - dyn_cast<CompoundLiteralExpr>(ArgExpr)) - if (const InitListExpr *ILE = - dyn_cast<InitListExpr>(CLE->getInitializer())) - ArgExpr = ILE->getInit(0); - } - - bool Result; - if (ArgExpr->EvaluateAsBooleanCondition(Result, Context) && !Result) - Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); - } -} - Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { return llvm::StringSwitch<FormatStringType>(Format->getType()->getName()) .Case("scanf", FST_Scanf) @@ -2331,30 +2413,31 @@ public: void DoneProcessing(); void HandleIncompleteSpecifier(const char *startSpecifier, - unsigned specifierLen); + unsigned specifierLen) override; void HandleInvalidLengthModifier( - const analyze_format_string::FormatSpecifier &FS, - const analyze_format_string::ConversionSpecifier &CS, - const char *startSpecifier, unsigned specifierLen, unsigned DiagID); + const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, + unsigned DiagID); void HandleNonStandardLengthModifier( - const analyze_format_string::FormatSpecifier &FS, - const char *startSpecifier, unsigned specifierLen); + const analyze_format_string::FormatSpecifier &FS, + const char *startSpecifier, unsigned specifierLen); void HandleNonStandardConversionSpecifier( - const analyze_format_string::ConversionSpecifier &CS, - const char *startSpecifier, unsigned specifierLen); + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); - virtual void HandlePosition(const char *startPos, unsigned posLen); + void HandlePosition(const char *startPos, unsigned posLen) override; - virtual void HandleInvalidPosition(const char *startSpecifier, - unsigned specifierLen, - analyze_format_string::PositionContext p); + void HandleInvalidPosition(const char *startSpecifier, + unsigned specifierLen, + analyze_format_string::PositionContext p) override; - virtual void HandleZeroPosition(const char *startPos, unsigned posLen); + void HandleZeroPosition(const char *startPos, unsigned posLen) override; - void HandleNullChar(const char *nullCharacter); + void HandleNullChar(const char *nullCharacter) override; template <typename Range> static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall, @@ -2390,9 +2473,6 @@ protected: void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, bool IsStringLocation, Range StringRange, ArrayRef<FixItHint> Fixit = None); - - void CheckPositionalAndNonpositionalArgs( - const analyze_format_string::FormatSpecifier *FS); }; } @@ -2723,15 +2803,15 @@ public: ObjCContext(isObjC) {} - + bool HandleInvalidPrintfConversionSpecifier( const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, - unsigned specifierLen); - + unsigned specifierLen) override; + bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, - unsigned specifierLen); + unsigned specifierLen) override; bool checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, const char *StartSpecifier, unsigned SpecifierLen, @@ -2751,7 +2831,7 @@ public: const analyze_printf::OptionalFlag &flag, const char *startSpecifier, unsigned specifierLen); bool checkForCStrMembers(const analyze_printf::ArgType &AT, - const Expr *E, const CharSourceRange &CSR); + const Expr *E); }; } @@ -2885,11 +2965,12 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) { if (!RT) return Results; const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) + if (!RD || !RD->getDefinition()) return Results; - LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(), + LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(), Sema::LookupMemberName); + R.suppressDiagnostics(); // We just need to include all members of the right kind turned up by the // filter, at this point. @@ -2902,12 +2983,26 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) { return Results; } +/// Check if we could call '.c_str()' on an object. +/// +/// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't +/// allow the call, or if it would be ambiguous). +bool Sema::hasCStrMethod(const Expr *E) { + typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet; + MethodSet Results = + CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType()); + for (MethodSet::iterator MI = Results.begin(), ME = Results.end(); + MI != ME; ++MI) + if ((*MI)->getMinRequiredArguments() == 0) + return true; + return false; +} + // Check if a (w)string was passed when a (w)char* was needed, and offer a // better diagnostic if so. AT is assumed to be valid. // Returns true when a c_str() conversion method is found. bool CheckPrintfHandler::checkForCStrMembers( - const analyze_printf::ArgType &AT, const Expr *E, - const CharSourceRange &CSR) { + const analyze_printf::ArgType &AT, const Expr *E) { typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet; MethodSet Results = @@ -2916,11 +3011,10 @@ bool CheckPrintfHandler::checkForCStrMembers( for (MethodSet::iterator MI = Results.begin(), ME = Results.end(); MI != ME; ++MI) { const CXXMethodDecl *Method = *MI; - if (Method->getNumParams() == 0 && - AT.matchesType(S.Context, Method->getResultType())) { + if (Method->getMinRequiredArguments() == 0 && + AT.matchesType(S.Context, Method->getReturnType())) { // FIXME: Suggest parens if the expression needs them. - SourceLocation EndLoc = - S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()); + SourceLocation EndLoc = S.getLocForEndOfToken(E->getLocEnd()); S.Diag(E->getLocStart(), diag::note_printf_c_str) << "c_str()" << FixItHint::CreateInsertion(EndLoc, ".c_str()"); @@ -2994,7 +3088,7 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier ArgType(S.Context.IntTy) : ArgType::CStrTy; if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_conversion_argument_type_mismatch) + diag::warn_format_conversion_argument_type_mismatch) << AT.getRepresentativeType(S.Context) << Ex->getType() << getSpecifierRange(startSpecifier, specifierLen) << Ex->getSourceRange(); @@ -3005,7 +3099,7 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier const analyze_printf::ArgType &AT2 = ArgType::CStrTy; if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType())) S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_conversion_argument_type_mismatch) + diag::warn_format_conversion_argument_type_mismatch) << AT2.getRepresentativeType(S.Context) << Ex->getType() << getSpecifierRange(startSpecifier, specifierLen) << Ex->getSourceRange(); @@ -3169,6 +3263,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ExprTy = S.Context.CharTy; } + // Look through enums to their underlying type. + bool IsEnum = false; + if (auto EnumTy = ExprTy->getAs<EnumType>()) { + ExprTy = EnumTy->getDecl()->getIntegerType(); + IsEnum = true; + } + // %C in an Objective-C context prints a unichar, not a wchar_t. // If the argument is an integer of some kind, believe the %C and suggest // a cast instead of changing the conversion specifier. @@ -3241,8 +3342,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // In this case, the specifier is wrong and should be changed to match // the argument. EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << IntendedTy + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, @@ -3283,7 +3384,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(), CastFix.str())); - SourceLocation After = S.PP.getLocForEndOfToken(E->getLocEnd()); + SourceLocation After = S.getLocForEndOfToken(E->getLocEnd()); Hints.push_back(FixItHint::CreateInsertion(After, ")")); } @@ -3294,7 +3395,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, StringRef Name = cast<TypedefType>(ExprTy)->getDecl()->getName(); EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast) - << Name << IntendedTy + << Name << IntendedTy << IsEnum << E->getSourceRange(), E->getLocStart(), /*IsStringLocation=*/false, SpecRange, Hints); @@ -3303,8 +3404,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // specifier, but we've decided that the specifier is probably correct // and we should cast instead. Just use the normal warning message. EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, SpecRange, Hints); @@ -3320,8 +3421,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, case Sema::VAK_Valid: case Sema::VAK_ValidInCXX11: EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum << CSR << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, CSR); @@ -3337,7 +3438,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, << CSR << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, CSR); - checkForCStrMembers(AT, E, CSR); + checkForCStrMembers(AT, E); break; case Sema::VAK_Invalid: @@ -3389,14 +3490,14 @@ public: bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, - unsigned specifierLen); + unsigned specifierLen) override; bool HandleInvalidScanfConversionSpecifier( const analyze_scanf::ScanfSpecifier &FS, const char *startSpecifier, - unsigned specifierLen); + unsigned specifierLen) override; - void HandleIncompleteScanList(const char *start, const char *end); + void HandleIncompleteScanList(const char *start, const char *end) override; }; } @@ -3501,8 +3602,9 @@ bool CheckScanfHandler::HandleScanfSpecifier( const analyze_format_string::ArgType &AT = FS.getArgType(S.Context); if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) { ScanfSpecifier fixedFS = FS; - bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(), - S.Context); + bool success = fixedFS.fixType(Ex->getType(), + Ex->IgnoreImpCasts()->getType(), + S.getLangOpts(), S.Context); if (success) { // Get the fix string from the fixed format specifier. @@ -3511,8 +3613,8 @@ bool CheckScanfHandler::HandleScanfSpecifier( fixedFS.toString(os); EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false << Ex->getSourceRange(), Ex->getLocStart(), /*IsStringLocation*/false, @@ -3522,8 +3624,8 @@ bool CheckScanfHandler::HandleScanfSpecifier( os.str())); } else { EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false << Ex->getSourceRange(), Ex->getLocStart(), /*IsStringLocation*/false, @@ -3554,9 +3656,25 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, // Str - The format string. NOTE: this is NOT null-terminated! StringRef StrRef = FExpr->getString(); const char *Str = StrRef.data(); - unsigned StrLen = StrRef.size(); + // Account for cases where the string literal is truncated in a declaration. + const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType()); + assert(T && "String literal not of constant array type!"); + size_t TypeSize = T->getSize().getZExtValue(); + size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size()); const unsigned numDataArgs = Args.size() - firstDataArg; - + + // Emit a warning if the string literal is truncated and does not contain an + // embedded null character. + if (TypeSize <= StrRef.size() && + StrRef.substr(0, TypeSize).find('\0') == StringRef::npos) { + CheckFormatHandler::EmitFormatDiagnostic( + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_printf_format_string_not_null_terminated), + FExpr->getLocStart(), + /*IsStringLocation=*/true, OrigFormatExpr->getSourceRange()); + return; + } + // CHECK: empty format string? if (StrLen == 0 && numDataArgs > 0) { CheckFormatHandler::EmitFormatDiagnostic( @@ -3588,17 +3706,452 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, } // TODO: handle other formats } +//===--- CHECK: Warn on use of wrong absolute value function. -------------===// + +// Returns the related absolute value function that is larger, of 0 if one +// does not exist. +static unsigned getLargerAbsoluteValueFunction(unsigned AbsFunction) { + switch (AbsFunction) { + default: + return 0; + + case Builtin::BI__builtin_abs: + return Builtin::BI__builtin_labs; + case Builtin::BI__builtin_labs: + return Builtin::BI__builtin_llabs; + case Builtin::BI__builtin_llabs: + return 0; + + case Builtin::BI__builtin_fabsf: + return Builtin::BI__builtin_fabs; + case Builtin::BI__builtin_fabs: + return Builtin::BI__builtin_fabsl; + case Builtin::BI__builtin_fabsl: + return 0; + + case Builtin::BI__builtin_cabsf: + return Builtin::BI__builtin_cabs; + case Builtin::BI__builtin_cabs: + return Builtin::BI__builtin_cabsl; + case Builtin::BI__builtin_cabsl: + return 0; + + case Builtin::BIabs: + return Builtin::BIlabs; + case Builtin::BIlabs: + return Builtin::BIllabs; + case Builtin::BIllabs: + return 0; + + case Builtin::BIfabsf: + return Builtin::BIfabs; + case Builtin::BIfabs: + return Builtin::BIfabsl; + case Builtin::BIfabsl: + return 0; + + case Builtin::BIcabsf: + return Builtin::BIcabs; + case Builtin::BIcabs: + return Builtin::BIcabsl; + case Builtin::BIcabsl: + return 0; + } +} + +// Returns the argument type of the absolute value function. +static QualType getAbsoluteValueArgumentType(ASTContext &Context, + unsigned AbsType) { + if (AbsType == 0) + return QualType(); + + ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None; + QualType BuiltinType = Context.GetBuiltinType(AbsType, Error); + if (Error != ASTContext::GE_None) + return QualType(); + + const FunctionProtoType *FT = BuiltinType->getAs<FunctionProtoType>(); + if (!FT) + return QualType(); + + if (FT->getNumParams() != 1) + return QualType(); + + return FT->getParamType(0); +} + +// Returns the best absolute value function, or zero, based on type and +// current absolute value function. +static unsigned getBestAbsFunction(ASTContext &Context, QualType ArgType, + unsigned AbsFunctionKind) { + unsigned BestKind = 0; + uint64_t ArgSize = Context.getTypeSize(ArgType); + for (unsigned Kind = AbsFunctionKind; Kind != 0; + Kind = getLargerAbsoluteValueFunction(Kind)) { + QualType ParamType = getAbsoluteValueArgumentType(Context, Kind); + if (Context.getTypeSize(ParamType) >= ArgSize) { + if (BestKind == 0) + BestKind = Kind; + else if (Context.hasSameType(ParamType, ArgType)) { + BestKind = Kind; + break; + } + } + } + return BestKind; +} + +enum AbsoluteValueKind { + AVK_Integer, + AVK_Floating, + AVK_Complex +}; + +static AbsoluteValueKind getAbsoluteValueKind(QualType T) { + if (T->isIntegralOrEnumerationType()) + return AVK_Integer; + if (T->isRealFloatingType()) + return AVK_Floating; + if (T->isAnyComplexType()) + return AVK_Complex; + + llvm_unreachable("Type not integer, floating, or complex"); +} + +// Changes the absolute value function to a different type. Preserves whether +// the function is a builtin. +static unsigned changeAbsFunction(unsigned AbsKind, + AbsoluteValueKind ValueKind) { + switch (ValueKind) { + case AVK_Integer: + switch (AbsKind) { + default: + return 0; + case Builtin::BI__builtin_fabsf: + case Builtin::BI__builtin_fabs: + case Builtin::BI__builtin_fabsl: + case Builtin::BI__builtin_cabsf: + case Builtin::BI__builtin_cabs: + case Builtin::BI__builtin_cabsl: + return Builtin::BI__builtin_abs; + case Builtin::BIfabsf: + case Builtin::BIfabs: + case Builtin::BIfabsl: + case Builtin::BIcabsf: + case Builtin::BIcabs: + case Builtin::BIcabsl: + return Builtin::BIabs; + } + case AVK_Floating: + switch (AbsKind) { + default: + return 0; + case Builtin::BI__builtin_abs: + case Builtin::BI__builtin_labs: + case Builtin::BI__builtin_llabs: + case Builtin::BI__builtin_cabsf: + case Builtin::BI__builtin_cabs: + case Builtin::BI__builtin_cabsl: + return Builtin::BI__builtin_fabsf; + case Builtin::BIabs: + case Builtin::BIlabs: + case Builtin::BIllabs: + case Builtin::BIcabsf: + case Builtin::BIcabs: + case Builtin::BIcabsl: + return Builtin::BIfabsf; + } + case AVK_Complex: + switch (AbsKind) { + default: + return 0; + case Builtin::BI__builtin_abs: + case Builtin::BI__builtin_labs: + case Builtin::BI__builtin_llabs: + case Builtin::BI__builtin_fabsf: + case Builtin::BI__builtin_fabs: + case Builtin::BI__builtin_fabsl: + return Builtin::BI__builtin_cabsf; + case Builtin::BIabs: + case Builtin::BIlabs: + case Builtin::BIllabs: + case Builtin::BIfabsf: + case Builtin::BIfabs: + case Builtin::BIfabsl: + return Builtin::BIcabsf; + } + } + llvm_unreachable("Unable to convert function"); +} + +static unsigned getAbsoluteValueFunctionKind(const FunctionDecl *FDecl) { + const IdentifierInfo *FnInfo = FDecl->getIdentifier(); + if (!FnInfo) + return 0; + + switch (FDecl->getBuiltinID()) { + default: + return 0; + case Builtin::BI__builtin_abs: + case Builtin::BI__builtin_fabs: + case Builtin::BI__builtin_fabsf: + case Builtin::BI__builtin_fabsl: + case Builtin::BI__builtin_labs: + case Builtin::BI__builtin_llabs: + case Builtin::BI__builtin_cabs: + case Builtin::BI__builtin_cabsf: + case Builtin::BI__builtin_cabsl: + case Builtin::BIabs: + case Builtin::BIlabs: + case Builtin::BIllabs: + case Builtin::BIfabs: + case Builtin::BIfabsf: + case Builtin::BIfabsl: + case Builtin::BIcabs: + case Builtin::BIcabsf: + case Builtin::BIcabsl: + return FDecl->getBuiltinID(); + } + llvm_unreachable("Unknown Builtin type"); +} + +// If the replacement is valid, emit a note with replacement function. +// Additionally, suggest including the proper header if not already included. +static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range, + unsigned AbsKind, QualType ArgType) { + bool EmitHeaderHint = true; + const char *HeaderName = nullptr; + const char *FunctionName = nullptr; + if (S.getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) { + FunctionName = "std::abs"; + if (ArgType->isIntegralOrEnumerationType()) { + HeaderName = "cstdlib"; + } else if (ArgType->isRealFloatingType()) { + HeaderName = "cmath"; + } else { + llvm_unreachable("Invalid Type"); + } + + // Lookup all std::abs + if (NamespaceDecl *Std = S.getStdNamespace()) { + LookupResult R(S, &S.Context.Idents.get("abs"), Loc, Sema::LookupAnyName); + R.suppressDiagnostics(); + S.LookupQualifiedName(R, Std); + + for (const auto *I : R) { + const FunctionDecl *FDecl = nullptr; + if (const UsingShadowDecl *UsingD = dyn_cast<UsingShadowDecl>(I)) { + FDecl = dyn_cast<FunctionDecl>(UsingD->getTargetDecl()); + } else { + FDecl = dyn_cast<FunctionDecl>(I); + } + if (!FDecl) + continue; + + // Found std::abs(), check that they are the right ones. + if (FDecl->getNumParams() != 1) + continue; + + // Check that the parameter type can handle the argument. + QualType ParamType = FDecl->getParamDecl(0)->getType(); + if (getAbsoluteValueKind(ArgType) == getAbsoluteValueKind(ParamType) && + S.Context.getTypeSize(ArgType) <= + S.Context.getTypeSize(ParamType)) { + // Found a function, don't need the header hint. + EmitHeaderHint = false; + break; + } + } + } + } else { + FunctionName = S.Context.BuiltinInfo.GetName(AbsKind); + HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind); + + if (HeaderName) { + DeclarationName DN(&S.Context.Idents.get(FunctionName)); + LookupResult R(S, DN, Loc, Sema::LookupAnyName); + R.suppressDiagnostics(); + S.LookupName(R, S.getCurScope()); + + if (R.isSingleResult()) { + FunctionDecl *FD = dyn_cast<FunctionDecl>(R.getFoundDecl()); + if (FD && FD->getBuiltinID() == AbsKind) { + EmitHeaderHint = false; + } else { + return; + } + } else if (!R.empty()) { + return; + } + } + } + + S.Diag(Loc, diag::note_replace_abs_function) + << FunctionName << FixItHint::CreateReplacement(Range, FunctionName); + + if (!HeaderName) + return; + + if (!EmitHeaderHint) + return; + + S.Diag(Loc, diag::note_include_header_or_declare) << HeaderName + << FunctionName; +} + +static bool IsFunctionStdAbs(const FunctionDecl *FDecl) { + if (!FDecl) + return false; + + if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr("abs")) + return false; + + const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(FDecl->getDeclContext()); + + while (ND && ND->isInlineNamespace()) { + ND = dyn_cast<NamespaceDecl>(ND->getDeclContext()); + } + + if (!ND || !ND->getIdentifier() || !ND->getIdentifier()->isStr("std")) + return false; + + if (!isa<TranslationUnitDecl>(ND->getDeclContext())) + return false; + + return true; +} + +// Warn when using the wrong abs() function. +void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, + const FunctionDecl *FDecl, + IdentifierInfo *FnInfo) { + if (Call->getNumArgs() != 1) + return; + + unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl); + bool IsStdAbs = IsFunctionStdAbs(FDecl); + if (AbsKind == 0 && !IsStdAbs) + return; + + QualType ArgType = Call->getArg(0)->IgnoreParenImpCasts()->getType(); + QualType ParamType = Call->getArg(0)->getType(); + + // Unsigned types cannot be negative. Suggest removing the absolute value + // function call. + if (ArgType->isUnsignedIntegerType()) { + const char *FunctionName = + IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind); + Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType; + Diag(Call->getExprLoc(), diag::note_remove_abs) + << FunctionName + << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange()); + return; + } + + // std::abs has overloads which prevent most of the absolute value problems + // from occurring. + if (IsStdAbs) + return; + + AbsoluteValueKind ArgValueKind = getAbsoluteValueKind(ArgType); + AbsoluteValueKind ParamValueKind = getAbsoluteValueKind(ParamType); + + // The argument and parameter are the same kind. Check if they are the right + // size. + if (ArgValueKind == ParamValueKind) { + if (Context.getTypeSize(ArgType) <= Context.getTypeSize(ParamType)) + return; + + unsigned NewAbsKind = getBestAbsFunction(Context, ArgType, AbsKind); + Diag(Call->getExprLoc(), diag::warn_abs_too_small) + << FDecl << ArgType << ParamType; + + if (NewAbsKind == 0) + return; + + emitReplacement(*this, Call->getExprLoc(), + Call->getCallee()->getSourceRange(), NewAbsKind, ArgType); + return; + } + + // ArgValueKind != ParamValueKind + // The wrong type of absolute value function was used. Attempt to find the + // proper one. + unsigned NewAbsKind = changeAbsFunction(AbsKind, ArgValueKind); + NewAbsKind = getBestAbsFunction(Context, ArgType, NewAbsKind); + if (NewAbsKind == 0) + return; + + Diag(Call->getExprLoc(), diag::warn_wrong_absolute_value_type) + << FDecl << ParamValueKind << ArgValueKind; + + emitReplacement(*this, Call->getExprLoc(), + Call->getCallee()->getSourceRange(), NewAbsKind, ArgType); + return; +} + //===--- CHECK: Standard memory functions ---------------------------------===// -/// \brief Determine whether the given type is a dynamic class type (e.g., -/// whether it has a vtable). -static bool isDynamicClassType(QualType T) { - if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) - if (CXXRecordDecl *Definition = Record->getDefinition()) - if (Definition->isDynamicClass()) - return true; - - return false; +/// \brief Takes the expression passed to the size_t parameter of functions +/// such as memcmp, strncat, etc and warns if it's a comparison. +/// +/// This is to catch typos like `if (memcmp(&a, &b, sizeof(a) > 0))`. +static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E, + IdentifierInfo *FnName, + SourceLocation FnLoc, + SourceLocation RParenLoc) { + const BinaryOperator *Size = dyn_cast<BinaryOperator>(E); + if (!Size) + return false; + + // if E is binop and op is >, <, >=, <=, ==, &&, ||: + if (!Size->isComparisonOp() && !Size->isEqualityOp() && !Size->isLogicalOp()) + return false; + + SourceRange SizeRange = Size->getSourceRange(); + S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison) + << SizeRange << FnName; + S.Diag(FnLoc, diag::note_memsize_comparison_paren) + << FnName << FixItHint::CreateInsertion( + S.getLocForEndOfToken(Size->getLHS()->getLocEnd()), ")") + << FixItHint::CreateRemoval(RParenLoc); + S.Diag(SizeRange.getBegin(), diag::note_memsize_comparison_cast_silence) + << FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(") + << FixItHint::CreateInsertion(S.getLocForEndOfToken(SizeRange.getEnd()), + ")"); + + return true; +} + +/// \brief Determine whether the given type is or contains a dynamic class type +/// (e.g., whether it has a vtable). +static const CXXRecordDecl *getContainedDynamicClass(QualType T, + bool &IsContained) { + // Look through array types while ignoring qualifiers. + const Type *Ty = T->getBaseElementTypeUnsafe(); + IsContained = false; + + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + RD = RD ? RD->getDefinition() : nullptr; + if (!RD) + return nullptr; + + if (RD->isDynamicClass()) + return RD; + + // Check all the fields. If any bases were dynamic, the class is dynamic. + // It's impossible for a class to transitively contain itself by value, so + // infinite recursion is impossible. + for (auto *FD : RD->fields()) { + bool SubContained; + if (const CXXRecordDecl *ContainedRD = + getContainedDynamicClass(FD->getType(), SubContained)) { + IsContained = true; + return ContainedRD; + } + } + + return nullptr; } /// \brief If E is a sizeof expression, returns its argument expression, @@ -3609,7 +4162,7 @@ static const Expr *getSizeOfExprArg(const Expr* E) { if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType()) return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); - return 0; + return nullptr; } /// \brief If E is a sizeof expression, returns its argument type. @@ -3645,6 +4198,10 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2); const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts(); + if (CheckMemorySizeofForComparison(*this, LenExpr, FnName, + Call->getLocStart(), Call->getRParenLoc())) + return; + // We have special checking when the length is a sizeof expression. QualType SizeOfArgTy = getSizeOfArgType(LenExpr); const Expr *SizeOfArg = getSizeOfExprArg(LenExpr); @@ -3668,8 +4225,8 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, // expression IDs can be expensive, we only do this if the diagnostic is // enabled. if (SizeOfArg && - Diags.getDiagnosticLevel(diag::warn_sizeof_pointer_expr_memaccess, - SizeOfArg->getExprLoc())) { + !Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, + SizeOfArg->getExprLoc())) { // We only compute IDs for expressions if the warning is enabled, and // cache the sizeof arg's ID. if (SizeOfArgID == llvm::FoldingSetNodeID()) @@ -3695,7 +4252,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, SourceLocation SL = SizeOfArg->getExprLoc(); SourceRange DSR = Dest->getSourceRange(); SourceRange SSR = SizeOfArg->getSourceRange(); - SourceManager &SM = PP.getSourceManager(); + SourceManager &SM = getSourceManager(); if (SM.isMacroArgExpansion(SL)) { ReadableName = Lexer::getImmediateMacroName(SL, SM, LangOpts); @@ -3738,7 +4295,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, } // Always complain about dynamic classes. - if (isDynamicClassType(PointeeTy)) { + bool IsContained; + if (const CXXRecordDecl *ContainedRD = + getContainedDynamicClass(PointeeTy, IsContained)) { unsigned OperationType = 0; // "overwritten" if we're warning about the destination for any call @@ -3756,8 +4315,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, Dest->getExprLoc(), Dest, PDiag(diag::warn_dyn_class_memaccess) << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) - << FnName << PointeeTy - << OperationType + << FnName << IsContained << ContainedRD << OperationType << Call->getCallee()->getSourceRange()); } else if (PointeeTy.hasNonTrivialObjCLifetime() && BId != Builtin::BImemset) @@ -3827,7 +4385,11 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context); const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context); - const Expr *CompareWithSrc = NULL; + const Expr *CompareWithSrc = nullptr; + + if (CheckMemorySizeofForComparison(*this, SizeArg, FnName, + Call->getLocStart(), Call->getRParenLoc())) + return; // Look for 'strlcpy(dst, x, sizeof(x))' if (const Expr *Ex = getSizeOfExprArg(SizeArg)) @@ -3835,8 +4397,8 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, else { // Look for 'strlcpy(dst, x, strlen(x))' if (const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) { - if (SizeCall->isBuiltinCall() == Builtin::BIstrlen - && SizeCall->getNumArgs() == 1) + if (SizeCall->getBuiltinCallee() == Builtin::BIstrlen && + SizeCall->getNumArgs() == 1) CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context); } } @@ -3872,7 +4434,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, SmallString<128> sizeString; llvm::raw_svector_ostream OS(sizeString); OS << "sizeof("; - DstArg->printPretty(OS, 0, getPrintingPolicy()); + DstArg->printPretty(OS, nullptr, getPrintingPolicy()); OS << ")"; Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size) @@ -3892,10 +4454,10 @@ static const Expr *getStrlenExprArg(const Expr *E) { if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { const FunctionDecl *FD = CE->getDirectCallee(); if (!FD || FD->getMemoryFunctionKind() != Builtin::BIstrlen) - return 0; + return nullptr; return CE->getArg(0)->IgnoreParenCasts(); } - return 0; + return nullptr; } // Warn on anti-patterns as the 'size' argument to strncat. @@ -3910,6 +4472,10 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts(); const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts(); + if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getLocStart(), + CE->getRParenLoc())) + return; + // Identify common expressions, which are wrongly used as the size argument // to strncat and may lead to buffer overflows. unsigned PatternType = 0; @@ -3940,7 +4506,7 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, // Generate the diagnostic. SourceLocation SL = LenArg->getLocStart(); SourceRange SR = LenArg->getSourceRange(); - SourceManager &SM = PP.getSourceManager(); + SourceManager &SM = getSourceManager(); // If the function is defined as a builtin macro, do not show macro expansion. if (SM.isMacroArgExpansion(SL)) { @@ -3969,10 +4535,10 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, SmallString<128> sizeString; llvm::raw_svector_ostream OS(sizeString); OS << "sizeof("; - DstArg->printPretty(OS, 0, getPrintingPolicy()); + DstArg->printPretty(OS, nullptr, getPrintingPolicy()); OS << ") - "; OS << "strlen("; - DstArg->printPretty(OS, 0, getPrintingPolicy()); + DstArg->printPretty(OS, nullptr, getPrintingPolicy()); OS << ") - 1"; Diag(SL, diag::note_strncat_wrong_size) @@ -3988,23 +4554,23 @@ static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars, /// CheckReturnStackAddr - Check if a return statement returns the address /// of a stack variable. -void -Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, - SourceLocation ReturnLoc) { +static void +CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc) { - Expr *stackE = 0; + Expr *stackE = nullptr; SmallVector<DeclRefExpr *, 8> refVars; // Perform checking for returned stack addresses, local blocks, // label addresses or references to temporaries. if (lhsType->isPointerType() || - (!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) { - stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/0); + (!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) { + stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/nullptr); } else if (lhsType->isReferenceType()) { - stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/0); + stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/nullptr); } - if (stackE == 0) + if (!stackE) return; // Nothing suspicious was found. SourceLocation diagLoc; @@ -4022,16 +4588,16 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, } if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var. - Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref + S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref : diag::warn_ret_stack_addr) << DR->getDecl()->getDeclName() << diagRange; } else if (isa<BlockExpr>(stackE)) { // local block. - Diag(diagLoc, diag::err_ret_local_block) << diagRange; + S.Diag(diagLoc, diag::err_ret_local_block) << diagRange; } else if (isa<AddrLabelExpr>(stackE)) { // address of label. - Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; + S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; } else { // local temporary. - Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref - : diag::warn_ret_local_temp_addr) + S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref + : diag::warn_ret_local_temp_addr) << diagRange; } @@ -4044,8 +4610,8 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, // show the range of the expression. SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange() : stackE->getSourceRange(); - Diag(VD->getLocation(), diag::note_ref_var_local_bind) - << VD->getDeclName() << range; + S.Diag(VD->getLocation(), diag::note_ref_var_local_bind) + << VD->getDeclName() << range; } } @@ -4078,7 +4644,7 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, Decl *ParentDecl) { if (E->isTypeDependent()) - return NULL; + return nullptr; // We should only be called for evaluating pointer expressions. assert((E->getType()->isAnyPointerType() || @@ -4095,6 +4661,10 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, case Stmt::DeclRefExprClass: { DeclRefExpr *DR = cast<DeclRefExpr>(E); + // If we leave the immediate function, the lifetime isn't about to end. + if (DR->refersToEnclosingLocal()) + return nullptr; + if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) // If this is a reference variable, follow through to the expression that // it points to. @@ -4105,7 +4675,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, return EvalAddr(V->getInit(), refVars, ParentDecl); } - return NULL; + return nullptr; } case Stmt::UnaryOperatorClass: { @@ -4116,7 +4686,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, if (U->getOpcode() == UO_AddrOf) return EvalVal(U->getSubExpr(), refVars, ParentDecl); else - return NULL; + return nullptr; } case Stmt::BinaryOperatorClass: { @@ -4126,7 +4696,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, BinaryOperatorKind op = B->getOpcode(); if (op != BO_Add && op != BO_Sub) - return NULL; + return nullptr; Expr *Base = B->getLHS(); @@ -4144,24 +4714,25 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, ConditionalOperator *C = cast<ConditionalOperator>(E); // Handle the GNU extension for missing LHS. - if (Expr *lhsExpr = C->getLHS()) { - // In C++, we can have a throw-expression, which has 'void' type. - if (!lhsExpr->getType()->isVoidType()) - if (Expr* LHS = EvalAddr(lhsExpr, refVars, ParentDecl)) + // FIXME: That isn't a ConditionalOperator, so doesn't get here. + if (Expr *LHSExpr = C->getLHS()) { + // In C++, we can have a throw-expression, which has 'void' type. + if (!LHSExpr->getType()->isVoidType()) + if (Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl)) return LHS; } // In C++, we can have a throw-expression, which has 'void' type. if (C->getRHS()->getType()->isVoidType()) - return NULL; + return nullptr; return EvalAddr(C->getRHS(), refVars, ParentDecl); } - + case Stmt::BlockExprClass: if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures()) return E; // local block. - return NULL; + return nullptr; case Stmt::AddrLabelExprClass: return E; // address of label. @@ -4182,7 +4753,6 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, case Stmt::CXXReinterpretCastExprClass: { Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); switch (cast<CastExpr>(E)->getCastKind()) { - case CK_BitCast: case CK_LValueToRValue: case CK_NoOp: case CK_BaseToDerived: @@ -4197,8 +4767,16 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, case CK_ArrayToPointerDecay: return EvalVal(SubExpr, refVars, ParentDecl); + case CK_BitCast: + if (SubExpr->getType()->isAnyPointerType() || + SubExpr->getType()->isBlockPointerType() || + SubExpr->getType()->isObjCQualifiedIdType()) + return EvalAddr(SubExpr, refVars, ParentDecl); + else + return nullptr; + default: - return 0; + return nullptr; } } @@ -4212,7 +4790,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars, // Everything else: we simply don't reason about them. default: - return NULL; + return nullptr; } } @@ -4238,7 +4816,7 @@ do { E = IE->getSubExpr(); continue; } - return NULL; + return nullptr; } case Stmt::ExprWithCleanupsClass: @@ -4250,6 +4828,10 @@ do { // local storage within the function, and if so, return the expression. DeclRefExpr *DR = cast<DeclRefExpr>(E); + // If we leave the immediate function, the lifetime isn't about to end. + if (DR->refersToEnclosingLocal()) + return nullptr; + if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) { // Check if it refers to itself, e.g. "int& i = i;". if (V == ParentDecl) @@ -4269,7 +4851,7 @@ do { } } - return NULL; + return nullptr; } case Stmt::UnaryOperatorClass: { @@ -4281,7 +4863,7 @@ do { if (U->getOpcode() == UO_Deref) return EvalAddr(U->getSubExpr(), refVars, ParentDecl); - return NULL; + return nullptr; } case Stmt::ArraySubscriptExprClass: { @@ -4297,9 +4879,16 @@ do { ConditionalOperator *C = cast<ConditionalOperator>(E); // Handle the GNU extension for missing LHS. - if (Expr *lhsExpr = C->getLHS()) - if (Expr *LHS = EvalVal(lhsExpr, refVars, ParentDecl)) - return LHS; + if (Expr *LHSExpr = C->getLHS()) { + // In C++, we can have a throw-expression, which has 'void' type. + if (!LHSExpr->getType()->isVoidType()) + if (Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl)) + return LHS; + } + + // In C++, we can have a throw-expression, which has 'void' type. + if (C->getRHS()->getType()->isVoidType()) + return nullptr; return EvalVal(C->getRHS(), refVars, ParentDecl); } @@ -4310,12 +4899,12 @@ do { // Check for indirect access. We only want direct field accesses. if (M->isArrow()) - return NULL; + return nullptr; // Check whether the member type is itself a reference, in which case // we're not going to refer to the member, but to what the member refers to. if (M->getMemberDecl()->getType()->isReferenceType()) - return NULL; + return nullptr; return EvalVal(M->getBase(), refVars, ParentDecl); } @@ -4335,11 +4924,43 @@ do { return E; // Everything else: we simply don't reason about them. - return NULL; + return nullptr; } } while (true); } +void +Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc, + bool isObjCMethod, + const AttrVec *Attrs, + const FunctionDecl *FD) { + CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc); + + // Check if the return value is null but should not be. + if (Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs) && + CheckNonNullExpr(*this, RetValExp)) + Diag(ReturnLoc, diag::warn_null_ret) + << (isObjCMethod ? 1 : 0) << RetValExp->getSourceRange(); + + // C++11 [basic.stc.dynamic.allocation]p4: + // If an allocation function declared with a non-throwing + // exception-specification fails to allocate storage, it shall return + // a null pointer. Any other allocation function that fails to allocate + // storage shall indicate failure only by throwing an exception [...] + if (FD) { + OverloadedOperatorKind Op = FD->getOverloadedOperator(); + if (Op == OO_New || Op == OO_Array_New) { + const FunctionProtoType *Proto + = FD->getType()->castAs<FunctionProtoType>(); + if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) && + CheckNonNullExpr(*this, RetValExp)) + Diag(ReturnLoc, diag::warn_operator_new_returns_null) + << FD << getLangOpts().CPlusPlus11; + } + } +} + //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// /// Check for comparisons of floating point operands using != and ==. @@ -4372,11 +4993,11 @@ void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) { // Check for comparisons with builtin types. if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen)) - if (CL->isBuiltinCall()) + if (CL->getBuiltinCallee()) return; if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen)) - if (CR->isBuiltinCall()) + if (CR->getBuiltinCallee()) return; // Emit the diagnostic. @@ -4421,6 +5042,8 @@ struct IntRange { T = VT->getElementType().getTypePtr(); if (const ComplexType *CT = dyn_cast<ComplexType>(T)) T = CT->getElementType().getTypePtr(); + if (const AtomicType *AT = dyn_cast<AtomicType>(T)) + T = AT->getValueType().getTypePtr(); // For enum types, use the known bit width of the enumerators. if (const EnumType *ET = dyn_cast<EnumType>(T)) { @@ -4456,6 +5079,8 @@ struct IntRange { T = VT->getElementType().getTypePtr(); if (const ComplexType *CT = dyn_cast<ComplexType>(T)) T = CT->getElementType().getTypePtr(); + if (const AtomicType *AT = dyn_cast<AtomicType>(T)) + T = AT->getValueType().getTypePtr(); if (const EnumType *ET = dyn_cast<EnumType>(T)) T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr(); @@ -4855,95 +5480,189 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, if (!S.ActiveTemplateInstantiations.empty()) return; + // TODO: Investigate using GetExprRange() to get tighter bounds + // on the bit ranges. + QualType OtherT = Other->getType(); + if (const AtomicType *AT = dyn_cast<AtomicType>(OtherT)) + OtherT = AT->getValueType(); + IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); + unsigned OtherWidth = OtherRange.Width; + + bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue(); + // 0 values are handled later by CheckTrivialUnsignedComparison(). - if (Value == 0) + if ((Value == 0) && (!OtherIsBooleanType)) return; BinaryOperatorKind op = E->getOpcode(); - QualType OtherT = Other->getType(); - QualType ConstantT = Constant->getType(); - QualType CommonT = E->getLHS()->getType(); - if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT)) - return; - assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) - && "comparison with non-integer type"); + bool IsTrue = true; + + // Used for diagnostic printout. + enum { + LiteralConstant = 0, + CXXBoolLiteralTrue, + CXXBoolLiteralFalse + } LiteralOrBoolConstant = LiteralConstant; - bool ConstantSigned = ConstantT->isSignedIntegerType(); - bool CommonSigned = CommonT->isSignedIntegerType(); + if (!OtherIsBooleanType) { + QualType ConstantT = Constant->getType(); + QualType CommonT = E->getLHS()->getType(); - bool EqualityOnly = false; + if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT)) + return; + assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) && + "comparison with non-integer type"); - // TODO: Investigate using GetExprRange() to get tighter bounds on - // on the bit ranges. - IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); - unsigned OtherWidth = OtherRange.Width; - - if (CommonSigned) { - // The common type is signed, therefore no signed to unsigned conversion. - if (!OtherRange.NonNegative) { - // Check that the constant is representable in type OtherT. - if (ConstantSigned) { - if (OtherWidth >= Value.getMinSignedBits()) - return; - } else { // !ConstantSigned - if (OtherWidth >= Value.getActiveBits() + 1) - return; + bool ConstantSigned = ConstantT->isSignedIntegerType(); + bool CommonSigned = CommonT->isSignedIntegerType(); + + bool EqualityOnly = false; + + if (CommonSigned) { + // The common type is signed, therefore no signed to unsigned conversion. + if (!OtherRange.NonNegative) { + // Check that the constant is representable in type OtherT. + if (ConstantSigned) { + if (OtherWidth >= Value.getMinSignedBits()) + return; + } else { // !ConstantSigned + if (OtherWidth >= Value.getActiveBits() + 1) + return; + } + } else { // !OtherSigned + // Check that the constant is representable in type OtherT. + // Negative values are out of range. + if (ConstantSigned) { + if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits()) + return; + } else { // !ConstantSigned + if (OtherWidth >= Value.getActiveBits()) + return; + } } - } else { // !OtherSigned - // Check that the constant is representable in type OtherT. - // Negative values are out of range. - if (ConstantSigned) { - if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits()) - return; - } else { // !ConstantSigned + } else { // !CommonSigned + if (OtherRange.NonNegative) { if (OtherWidth >= Value.getActiveBits()) return; + } else { // OtherSigned + assert(!ConstantSigned && + "Two signed types converted to unsigned types."); + // Check to see if the constant is representable in OtherT. + if (OtherWidth > Value.getActiveBits()) + return; + // Check to see if the constant is equivalent to a negative value + // cast to CommonT. + if (S.Context.getIntWidth(ConstantT) == + S.Context.getIntWidth(CommonT) && + Value.isNegative() && Value.getMinSignedBits() <= OtherWidth) + return; + // The constant value rests between values that OtherT can represent + // after conversion. Relational comparison still works, but equality + // comparisons will be tautological. + EqualityOnly = true; } } - } else { // !CommonSigned - if (OtherRange.NonNegative) { - if (OtherWidth >= Value.getActiveBits()) - return; - } else if (!OtherRange.NonNegative && !ConstantSigned) { - // Check to see if the constant is representable in OtherT. - if (OtherWidth > Value.getActiveBits()) - return; - // Check to see if the constant is equivalent to a negative value - // cast to CommonT. - if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) && - Value.isNegative() && Value.getMinSignedBits() <= OtherWidth) - return; - // The constant value rests between values that OtherT can represent after - // conversion. Relational comparison still works, but equality - // comparisons will be tautological. - EqualityOnly = true; - } else { // OtherSigned && ConstantSigned - assert(0 && "Two signed types converted to unsigned types."); - } - } - bool PositiveConstant = !ConstantSigned || Value.isNonNegative(); + bool PositiveConstant = !ConstantSigned || Value.isNonNegative(); - bool IsTrue = true; - if (op == BO_EQ || op == BO_NE) { - IsTrue = op == BO_NE; - } else if (EqualityOnly) { - return; - } else if (RhsConstant) { - if (op == BO_GT || op == BO_GE) - IsTrue = !PositiveConstant; - else // op == BO_LT || op == BO_LE - IsTrue = PositiveConstant; + if (op == BO_EQ || op == BO_NE) { + IsTrue = op == BO_NE; + } else if (EqualityOnly) { + return; + } else if (RhsConstant) { + if (op == BO_GT || op == BO_GE) + IsTrue = !PositiveConstant; + else // op == BO_LT || op == BO_LE + IsTrue = PositiveConstant; + } else { + if (op == BO_LT || op == BO_LE) + IsTrue = !PositiveConstant; + else // op == BO_GT || op == BO_GE + IsTrue = PositiveConstant; + } } else { - if (op == BO_LT || op == BO_LE) - IsTrue = !PositiveConstant; - else // op == BO_GT || op == BO_GE - IsTrue = PositiveConstant; + // Other isKnownToHaveBooleanValue + enum CompareBoolWithConstantResult { AFals, ATrue, Unkwn }; + enum ConstantValue { LT_Zero, Zero, One, GT_One, SizeOfConstVal }; + enum ConstantSide { Lhs, Rhs, SizeOfConstSides }; + + static const struct LinkedConditions { + CompareBoolWithConstantResult BO_LT_OP[SizeOfConstSides][SizeOfConstVal]; + CompareBoolWithConstantResult BO_GT_OP[SizeOfConstSides][SizeOfConstVal]; + CompareBoolWithConstantResult BO_LE_OP[SizeOfConstSides][SizeOfConstVal]; + CompareBoolWithConstantResult BO_GE_OP[SizeOfConstSides][SizeOfConstVal]; + CompareBoolWithConstantResult BO_EQ_OP[SizeOfConstSides][SizeOfConstVal]; + CompareBoolWithConstantResult BO_NE_OP[SizeOfConstSides][SizeOfConstVal]; + + } TruthTable = { + // Constant on LHS. | Constant on RHS. | + // LT_Zero| Zero | One |GT_One| LT_Zero| Zero | One |GT_One| + { { ATrue, Unkwn, AFals, AFals }, { AFals, AFals, Unkwn, ATrue } }, + { { AFals, AFals, Unkwn, ATrue }, { ATrue, Unkwn, AFals, AFals } }, + { { ATrue, ATrue, Unkwn, AFals }, { AFals, Unkwn, ATrue, ATrue } }, + { { AFals, Unkwn, ATrue, ATrue }, { ATrue, ATrue, Unkwn, AFals } }, + { { AFals, Unkwn, Unkwn, AFals }, { AFals, Unkwn, Unkwn, AFals } }, + { { ATrue, Unkwn, Unkwn, ATrue }, { ATrue, Unkwn, Unkwn, ATrue } } + }; + + bool ConstantIsBoolLiteral = isa<CXXBoolLiteralExpr>(Constant); + + enum ConstantValue ConstVal = Zero; + if (Value.isUnsigned() || Value.isNonNegative()) { + if (Value == 0) { + LiteralOrBoolConstant = + ConstantIsBoolLiteral ? CXXBoolLiteralFalse : LiteralConstant; + ConstVal = Zero; + } else if (Value == 1) { + LiteralOrBoolConstant = + ConstantIsBoolLiteral ? CXXBoolLiteralTrue : LiteralConstant; + ConstVal = One; + } else { + LiteralOrBoolConstant = LiteralConstant; + ConstVal = GT_One; + } + } else { + ConstVal = LT_Zero; + } + + CompareBoolWithConstantResult CmpRes; + + switch (op) { + case BO_LT: + CmpRes = TruthTable.BO_LT_OP[RhsConstant][ConstVal]; + break; + case BO_GT: + CmpRes = TruthTable.BO_GT_OP[RhsConstant][ConstVal]; + break; + case BO_LE: + CmpRes = TruthTable.BO_LE_OP[RhsConstant][ConstVal]; + break; + case BO_GE: + CmpRes = TruthTable.BO_GE_OP[RhsConstant][ConstVal]; + break; + case BO_EQ: + CmpRes = TruthTable.BO_EQ_OP[RhsConstant][ConstVal]; + break; + case BO_NE: + CmpRes = TruthTable.BO_NE_OP[RhsConstant][ConstVal]; + break; + default: + CmpRes = Unkwn; + break; + } + + if (CmpRes == AFals) { + IsTrue = false; + } else if (CmpRes == ATrue) { + IsTrue = true; + } else { + return; + } } // If this is a comparison to an enum constant, include that // constant in the diagnostic. - const EnumConstantDecl *ED = 0; + const EnumConstantDecl *ED = nullptr; if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant)) ED = dyn_cast<EnumConstantDecl>(DR->getDecl()); @@ -4954,9 +5673,12 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, else OS << Value; - S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare) - << OS.str() << OtherT << IsTrue - << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + S.DiagRuntimeBehavior( + E->getOperatorLoc(), E, + S.PDiag(diag::warn_out_of_range_compare) + << OS.str() << LiteralOrBoolConstant + << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); } /// Analyze the operands of the given comparison. Implements the @@ -5245,7 +5967,7 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, } void CheckImplicitConversion(Sema &S, Expr *E, QualType T, - SourceLocation CC, bool *ICContext = 0) { + SourceLocation CC, bool *ICContext = nullptr) { if (E->isTypeDependent() || E->isValueDependent()) return; const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); @@ -5265,39 +5987,21 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (Target->isSpecificBuiltinType(BuiltinType::Bool)) { if (isa<StringLiteral>(E)) // Warn on string literal to bool. Checks for string literals in logical - // expressions, for instances, assert(0 && "error here"), is prevented - // by a check in AnalyzeImplicitConversions(). + // and expressions, for instance, assert(0 && "error here"), are + // prevented by a check in AnalyzeImplicitConversions(). return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_string_literal_to_bool); - if (Source->isFunctionType()) { - // Warn on function to bool. Checks free functions and static member - // functions. Weakly imported functions are excluded from the check, - // since it's common to test their value to check whether the linker - // found a definition for them. - ValueDecl *D = 0; - if (DeclRefExpr* R = dyn_cast<DeclRefExpr>(E)) { - D = R->getDecl(); - } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) { - D = M->getMemberDecl(); - } - - if (D && !D->isWeak()) { - if (FunctionDecl* F = dyn_cast<FunctionDecl>(D)) { - S.Diag(E->getExprLoc(), diag::warn_impcast_function_to_bool) - << F << E->getSourceRange() << SourceRange(CC); - S.Diag(E->getExprLoc(), diag::note_function_to_bool_silence) - << FixItHint::CreateInsertion(E->getExprLoc(), "&"); - QualType ReturnType; - UnresolvedSet<4> NonTemplateOverloads; - S.tryExprAsCall(*E, ReturnType, NonTemplateOverloads); - if (!ReturnType.isNull() - && ReturnType->isSpecificBuiltinType(BuiltinType::Bool)) - S.Diag(E->getExprLoc(), diag::note_function_to_bool_call) - << FixItHint::CreateInsertion( - S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()"); - return; - } - } + if (isa<ObjCStringLiteral>(E) || isa<ObjCArrayLiteral>(E) || + isa<ObjCDictionaryLiteral>(E) || isa<ObjCBoxedExpr>(E)) { + // This covers the literal expressions that evaluate to Objective-C + // objects. + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_objective_c_literal_to_bool); + } + if (Source->isPointerType() || Source->canDecayToPointerType()) { + // Warn on pointer to bool conversion that is always true. + S.DiagnoseAlwaysNonNullPointer(E, Expr::NPCK_NotNull, /*IsEqual*/ false, + SourceRange(CC)); } } @@ -5317,6 +6021,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, Source = cast<VectorType>(Source)->getElementType().getTypePtr(); Target = cast<VectorType>(Target)->getElementType().getTypePtr(); } + if (auto VecTy = dyn_cast<VectorType>(Target)) + Target = VecTy->getElementType().getTypePtr(); // Strip complex types. if (isa<ComplexType>(Source)) { @@ -5535,8 +6241,7 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E, if (!Suspicious) return; // ...but it's currently ignored... - if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional, - CC)) + if (!S.Diags.isIgnored(diag::warn_impcast_integer_sign_conditional, CC)) return; // ...then check whether it would have warned about either of the @@ -5560,7 +6265,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { if (E->isTypeDependent() || E->isValueDependent()) return; - + // For conditional operators, we analyze the arguments as if they // were being fed directly into the output. if (isa<ConditionalOperator>(E)) { @@ -5617,15 +6322,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { // Now just recurse over the expression's children. CC = E->getExprLoc(); BinaryOperator *BO = dyn_cast<BinaryOperator>(E); - bool IsLogicalOperator = BO && BO->isLogicalOp(); + bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd; for (Stmt::child_range I = E->children(); I; ++I) { Expr *ChildExpr = dyn_cast_or_null<Expr>(*I); if (!ChildExpr) continue; - if (IsLogicalOperator && + if (IsLogicalAndOperator && isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts())) - // Ignore checking string literals that are in logical operators. + // Ignore checking string literals that are in logical and operators. + // This is a common pattern for asserts. continue; AnalyzeImplicitConversions(S, ChildExpr, CC); } @@ -5633,6 +6339,172 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { } // end anonymous namespace +enum { + AddressOf, + FunctionPointer, + ArrayPointer +}; + +// Helper function for Sema::DiagnoseAlwaysNonNullPointer. +// Returns true when emitting a warning about taking the address of a reference. +static bool CheckForReference(Sema &SemaRef, const Expr *E, + PartialDiagnostic PD) { + E = E->IgnoreParenImpCasts(); + + const FunctionDecl *FD = nullptr; + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (!DRE->getDecl()->getType()->isReferenceType()) + return false; + } else if (const MemberExpr *M = dyn_cast<MemberExpr>(E)) { + if (!M->getMemberDecl()->getType()->isReferenceType()) + return false; + } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) { + if (!Call->getCallReturnType()->isReferenceType()) + return false; + FD = Call->getDirectCallee(); + } else { + return false; + } + + SemaRef.Diag(E->getExprLoc(), PD); + + // If possible, point to location of function. + if (FD) { + SemaRef.Diag(FD->getLocation(), diag::note_reference_is_return_value) << FD; + } + + return true; +} + +/// \brief Diagnose pointers that are always non-null. +/// \param E the expression containing the pointer +/// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is +/// compared to a null pointer +/// \param IsEqual True when the comparison is equal to a null pointer +/// \param Range Extra SourceRange to highlight in the diagnostic +void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, + Expr::NullPointerConstantKind NullKind, + bool IsEqual, SourceRange Range) { + if (!E) + return; + + // Don't warn inside macros. + if (E->getExprLoc().isMacroID()) + return; + E = E->IgnoreImpCasts(); + + const bool IsCompare = NullKind != Expr::NPCK_NotNull; + + if (isa<CXXThisExpr>(E)) { + unsigned DiagID = IsCompare ? diag::warn_this_null_compare + : diag::warn_this_bool_conversion; + Diag(E->getExprLoc(), DiagID) << E->getSourceRange() << Range << IsEqual; + return; + } + + bool IsAddressOf = false; + + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { + if (UO->getOpcode() != UO_AddrOf) + return; + IsAddressOf = true; + E = UO->getSubExpr(); + } + + if (IsAddressOf) { + unsigned DiagID = IsCompare + ? diag::warn_address_of_reference_null_compare + : diag::warn_address_of_reference_bool_conversion; + PartialDiagnostic PD = PDiag(DiagID) << E->getSourceRange() << Range + << IsEqual; + if (CheckForReference(*this, E, PD)) { + return; + } + } + + // Expect to find a single Decl. Skip anything more complicated. + ValueDecl *D = nullptr; + if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) { + D = R->getDecl(); + } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) { + D = M->getMemberDecl(); + } + + // Weak Decls can be null. + if (!D || D->isWeak()) + return; + + QualType T = D->getType(); + const bool IsArray = T->isArrayType(); + const bool IsFunction = T->isFunctionType(); + + // Address of function is used to silence the function warning. + if (IsAddressOf && IsFunction) { + return; + } + + // Found nothing. + if (!IsAddressOf && !IsFunction && !IsArray) + return; + + // Pretty print the expression for the diagnostic. + std::string Str; + llvm::raw_string_ostream S(Str); + E->printPretty(S, nullptr, getPrintingPolicy()); + + unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare + : diag::warn_impcast_pointer_to_bool; + unsigned DiagType; + if (IsAddressOf) + DiagType = AddressOf; + else if (IsFunction) + DiagType = FunctionPointer; + else if (IsArray) + DiagType = ArrayPointer; + else + llvm_unreachable("Could not determine diagnostic."); + Diag(E->getExprLoc(), DiagID) << DiagType << S.str() << E->getSourceRange() + << Range << IsEqual; + + if (!IsFunction) + return; + + // Suggest '&' to silence the function warning. + Diag(E->getExprLoc(), diag::note_function_warning_silence) + << FixItHint::CreateInsertion(E->getLocStart(), "&"); + + // Check to see if '()' fixit should be emitted. + QualType ReturnType; + UnresolvedSet<4> NonTemplateOverloads; + tryExprAsCall(*E, ReturnType, NonTemplateOverloads); + if (ReturnType.isNull()) + return; + + if (IsCompare) { + // There are two cases here. If there is null constant, the only suggest + // for a pointer return type. If the null is 0, then suggest if the return + // type is a pointer or an integer type. + if (!ReturnType->isPointerType()) { + if (NullKind == Expr::NPCK_ZeroExpression || + NullKind == Expr::NPCK_ZeroLiteral) { + if (!ReturnType->isIntegerType()) + return; + } else { + return; + } + } + } else { // !IsCompare + // For function to bool, only suggest if the function pointer has bool + // return type. + if (!ReturnType->isSpecificBuiltinType(BuiltinType::Bool)) + return; + } + Diag(E->getExprLoc(), diag::note_function_to_function_call) + << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()"); +} + + /// Diagnoses "dangerous" implicit conversions within the given /// expression (which is a full expression). Implements -Wconversion /// and -Wsign-compare. @@ -5754,7 +6626,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { }; struct Usage { - Usage() : Use(0), Seq() {} + Usage() : Use(nullptr), Seq() {} Expr *Use; SequenceTree::Seq Seq; }; @@ -5854,7 +6726,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) // FIXME: If this is a reference, map through to its value. return DRE->getDecl(); - return 0; + return nullptr; } /// \brief Note that an object was modified or used by an expression. @@ -5914,8 +6786,8 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { public: SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList) - : Base(S.Context), SemaRef(S), Region(Tree.root()), ModAsSideEffect(0), - WorkList(WorkList), EvalTracker(0) { + : Base(S.Context), SemaRef(S), Region(Tree.root()), + ModAsSideEffect(nullptr), WorkList(WorkList), EvalTracker(nullptr) { Visit(E); } @@ -6200,7 +7072,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, // C99 6.9.1p5: If the declarator includes a parameter type list, the // declaration of each parameter shall include an identifier. if (CheckParameterNames && - Param->getIdentifier() == 0 && + Param->getIdentifier() == nullptr && !Param->isImplicit() && !getLangOpts().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); @@ -6223,11 +7095,23 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, // MSVC destroys objects passed by value in the callee. Therefore a // function definition which takes such a parameter must be able to call the - // object's destructor. - if (getLangOpts().CPlusPlus && - Context.getTargetInfo().getCXXABI().isArgumentDestroyedByCallee()) { - if (const RecordType *RT = Param->getType()->getAs<RecordType>()) - FinalizeVarWithDestructor(Param, RT); + // object's destructor. However, we don't perform any direct access check + // on the dtor. + if (getLangOpts().CPlusPlus && Context.getTargetInfo() + .getCXXABI() + .areArgsDestroyedLeftToRightInCallee()) { + if (!Param->isInvalidDecl()) { + if (const RecordType *RT = Param->getType()->getAs<RecordType>()) { + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (!ClassDecl->isInvalidDecl() && + !ClassDecl->hasIrrelevantDestructor() && + !ClassDecl->isDependentContext()) { + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); + MarkFunctionReferenced(Param->getLocation(), Destructor); + DiagnoseUseOfDecl(Destructor, Param->getLocation()); + } + } + } } } @@ -6239,9 +7123,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { // This is actually a lot of work to potentially be doing on every // cast; don't do it if we're ignoring -Wcast_align (as is the default). - if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align, - TRange.getBegin()) - == DiagnosticsEngine::Ignored) + if (getDiagnostics().isIgnored(diag::warn_cast_align, TRange.getBegin())) return; // Ignore dependent types. @@ -6355,7 +7237,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (IndexNegated) index = -index; - const NamedDecl *ND = NULL; + const NamedDecl *ND = nullptr; if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr)) ND = dyn_cast<NamedDecl>(DRE->getDecl()); if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr)) @@ -6498,7 +7380,7 @@ void Sema::CheckArrayAccess(const Expr *expr) { namespace { struct RetainCycleOwner { - RetainCycleOwner() : Variable(0), Indirect(false) {} + RetainCycleOwner() : Variable(nullptr), Indirect(false) {} VarDecl *Variable; SourceRange Range; SourceLocation Loc; @@ -6609,10 +7491,12 @@ namespace { struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> { FindCaptureVisitor(ASTContext &Context, VarDecl *variable) : EvaluatedExprVisitor<FindCaptureVisitor>(Context), - Variable(variable), Capturer(0) {} - + Context(Context), Variable(variable), Capturer(nullptr), + VarWillBeReased(false) {} + ASTContext &Context; VarDecl *Variable; Expr *Capturer; + bool VarWillBeReased; void VisitDeclRefExpr(DeclRefExpr *ref) { if (ref->getDecl() == Variable && !Capturer) @@ -6637,6 +7521,21 @@ namespace { if (OVE->getSourceExpr()) Visit(OVE->getSourceExpr()); } + void VisitBinaryOperator(BinaryOperator *BinOp) { + if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign) + return; + Expr *LHS = BinOp->getLHS(); + if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) { + if (DRE->getDecl() != Variable) + return; + if (Expr *RHS = BinOp->getRHS()) { + RHS = RHS->IgnoreParenCasts(); + llvm::APSInt Value; + VarWillBeReased = + (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0); + } + } + } }; } @@ -6653,7 +7552,7 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { e = ME->getInstanceReceiver(); if (!e) - return 0; + return nullptr; e = e->IgnoreParenCasts(); } } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) { @@ -6670,11 +7569,11 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { BlockExpr *block = dyn_cast<BlockExpr>(e); if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) - return 0; + return nullptr; FindCaptureVisitor visitor(S.Context, owner.Variable); visitor.Visit(block->getBlockDecl()->getBody()); - return visitor.Capturer; + return visitor.VarWillBeReased ? nullptr : visitor.Capturer; } static void diagnoseRetainCycle(Sema &S, Expr *capturer, @@ -6746,7 +7645,7 @@ void Sema::checkRetainCycles(Expr *receiver, Expr *argument) { void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) { RetainCycleOwner Owner; - if (!considerVariable(Var, /*DeclRefExpr=*/0, Owner)) + if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner)) return; // Because we don't have an expression for the variable, we have to set the @@ -6818,7 +7717,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS) { QualType LHSType; // PropertyRef on LHS type need be directly obtained from - // its declaration as it has a PsuedoType. + // its declaration as it has a PseudoType. ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens()); if (PRE && !PRE->isImplicitProperty()) { @@ -6833,9 +7732,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); if (LT == Qualifiers::OCL_Weak) { - DiagnosticsEngine::Level Level = - Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc); - if (Level != DiagnosticsEngine::Ignored) + if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) getCurFunction()->markSafeWeakUse(LHS); } @@ -6960,8 +7857,7 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S, return; // Skip expensive checks if diagnostic is disabled. - if (Diags.getDiagnosticLevel(DiagID, NBody->getSemiLoc()) == - DiagnosticsEngine::Ignored) + if (Diags.isIgnored(DiagID, NBody->getSemiLoc())) return; // Do the usual checks. @@ -7091,21 +7987,16 @@ bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1, RecordDecl *RD2) { llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields; - for (RecordDecl::field_iterator Field2 = RD2->field_begin(), - Field2End = RD2->field_end(); - Field2 != Field2End; ++Field2) { - UnmatchedFields.insert(*Field2); - } + for (auto *Field2 : RD2->fields()) + UnmatchedFields.insert(Field2); - for (RecordDecl::field_iterator Field1 = RD1->field_begin(), - Field1End = RD1->field_end(); - Field1 != Field1End; ++Field1) { + for (auto *Field1 : RD1->fields()) { llvm::SmallPtrSet<FieldDecl *, 8>::iterator I = UnmatchedFields.begin(), E = UnmatchedFields.end(); for ( ; I != E; ++I) { - if (isLayoutCompatible(C, *Field1, *I)) { + if (isLayoutCompatible(C, Field1, *I)) { bool Result = UnmatchedFields.erase(*I); (void) Result; assert(Result); @@ -7262,7 +8153,7 @@ bool GetMatchingCType( FoundWrongKind = false; // Variable declaration that has type_tag_for_datatype attribute. - const ValueDecl *VD = NULL; + const ValueDecl *VD = nullptr; uint64_t MagicValue; @@ -7270,10 +8161,7 @@ bool GetMatchingCType( return false; if (VD) { - for (specific_attr_iterator<TypeTagForDatatypeAttr> - I = VD->specific_attr_begin<TypeTagForDatatypeAttr>(), - E = VD->specific_attr_end<TypeTagForDatatypeAttr>(); - I != E; ++I) { + if (TypeTagForDatatypeAttr *I = VD->getAttr<TypeTagForDatatypeAttr>()) { if (I->getArgumentKind() != ArgumentKind) { FoundWrongKind = true; return false; @@ -7406,8 +8294,9 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, if (mismatch) Diag(ArgumentExpr->getExprLoc(), diag::warn_type_safety_type_mismatch) - << ArgumentType << ArgumentKind->getName() + << ArgumentType << ArgumentKind << TypeInfo.LayoutCompatible << RequiredType << ArgumentExpr->getSourceRange() << TypeTagExpr->getSourceRange(); } + |