diff options
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 781 |
1 files changed, 658 insertions, 123 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 8c3efdee9036..23a6fc3c4cd4 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -184,7 +184,7 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { return true; } - QualType ReturnTy = CE->getCallReturnType(); + QualType ReturnTy = CE->getCallReturnType(S.Context); QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() }; QualType BuiltinTy = S.Context.getFunctionType( ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo()); @@ -202,6 +202,28 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { return false; } +static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall, + Scope::ScopeFlags NeededScopeFlags, + unsigned DiagID) { + // Scopes aren't available during instantiation. Fortunately, builtin + // functions cannot be template args so they cannot be formed through template + // instantiation. Therefore checking once during the parse is sufficient. + if (!SemaRef.ActiveTemplateInstantiations.empty()) + return false; + + Scope *S = SemaRef.getCurScope(); + while (S && !S->isSEHExceptScope()) + S = S->getParent(); + if (!S || !(S->getFlags() & NeededScopeFlags)) { + auto *DRE = cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + SemaRef.Diag(TheCall->getExprLoc(), DiagID) + << DRE->getDecl()->getIdentifier(); + return true; + } + + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -301,6 +323,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinSetjmp(TheCall)) return ExprError(); break; + case Builtin::BI_setjmp: + case Builtin::BI_setjmpex: + if (checkArgCount(*this, TheCall, 1)) + return true; + break; case Builtin::BI__builtin_classify_type: if (checkArgCount(*this, TheCall, 1)) return true; @@ -465,6 +492,35 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinCallWithStaticChain(*this, TheCall)) return ExprError(); break; + + case Builtin::BI__exception_code: + case Builtin::BI_exception_code: { + if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHExceptScope, + diag::err_seh___except_block)) + return ExprError(); + break; + } + case Builtin::BI__exception_info: + case Builtin::BI_exception_info: { + if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHFilterScope, + diag::err_seh___except_filter)) + return ExprError(); + break; + } + + case Builtin::BI__GetExceptionInfo: + if (checkArgCount(*this, TheCall, 1)) + return ExprError(); + + if (CheckCXXThrowOperand( + TheCall->getLocStart(), + Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()), + TheCall)) + return ExprError(); + + TheCall->setType(Context.VoidPtrTy); + break; + } // Since the target specific builtins for each arch overlap, only check those @@ -490,11 +546,21 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::systemz: + if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; case llvm::Triple::x86: case llvm::Triple::x86_64: if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; default: break; } @@ -557,7 +623,10 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, case NeonTypeFlags::Poly16: return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy; case NeonTypeFlags::Poly64: - return Context.UnsignedLongTy; + if (IsInt64Long) + return Context.UnsignedLongTy; + else + return Context.UnsignedLongLongTy; case NeonTypeFlags::Poly128: break; case NeonTypeFlags::Float16: @@ -839,15 +908,161 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return SemaBuiltinConstantArgRange(TheCall, i, l, u); } +bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + unsigned i = 0, l = 0, u = 0; + bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde || + BuiltinID == PPC::BI__builtin_divdeu || + BuiltinID == PPC::BI__builtin_bpermd; + bool IsTarget64Bit = Context.getTargetInfo() + .getTypeWidth(Context + .getTargetInfo() + .getIntPtrType()) == 64; + bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe || + BuiltinID == PPC::BI__builtin_divweu || + BuiltinID == PPC::BI__builtin_divde || + BuiltinID == PPC::BI__builtin_divdeu; + + if (Is64BitBltin && !IsTarget64Bit) + return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt) + << TheCall->getSourceRange(); + + if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) || + (BuiltinID == PPC::BI__builtin_bpermd && + !Context.getTargetInfo().hasFeature("bpermd"))) + return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7) + << TheCall->getSourceRange(); + + switch (BuiltinID) { + default: return false; + case PPC::BI__builtin_altivec_crypto_vshasigmaw: + case PPC::BI__builtin_altivec_crypto_vshasigmad: + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 15); + case PPC::BI__builtin_tbegin: + case PPC::BI__builtin_tend: i = 0; l = 0; u = 1; break; + case PPC::BI__builtin_tsr: i = 0; l = 0; u = 7; break; + case PPC::BI__builtin_tabortwc: + case PPC::BI__builtin_tabortdc: i = 0; l = 0; u = 31; break; + case PPC::BI__builtin_tabortwci: + case PPC::BI__builtin_tabortdci: + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 31); + } + return SemaBuiltinConstantArgRange(TheCall, i, l, u); +} + +bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + if (BuiltinID == SystemZ::BI__builtin_tabort) { + Expr *Arg = TheCall->getArg(0); + llvm::APSInt AbortCode(32); + if (Arg->isIntegerConstantExpr(AbortCode, Context) && + AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256) + return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code) + << Arg->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 SystemZ::BI__builtin_s390_lcbb: i = 1; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_verimb: + case SystemZ::BI__builtin_s390_verimh: + case SystemZ::BI__builtin_s390_verimf: + case SystemZ::BI__builtin_s390_verimg: i = 3; l = 0; u = 255; break; + case SystemZ::BI__builtin_s390_vfaeb: + case SystemZ::BI__builtin_s390_vfaeh: + case SystemZ::BI__builtin_s390_vfaef: + case SystemZ::BI__builtin_s390_vfaebs: + case SystemZ::BI__builtin_s390_vfaehs: + case SystemZ::BI__builtin_s390_vfaefs: + case SystemZ::BI__builtin_s390_vfaezb: + case SystemZ::BI__builtin_s390_vfaezh: + case SystemZ::BI__builtin_s390_vfaezf: + case SystemZ::BI__builtin_s390_vfaezbs: + case SystemZ::BI__builtin_s390_vfaezhs: + case SystemZ::BI__builtin_s390_vfaezfs: i = 2; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vfidb: + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 15); + case SystemZ::BI__builtin_s390_vftcidb: i = 1; l = 0; u = 4095; break; + case SystemZ::BI__builtin_s390_vlbb: i = 1; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vpdi: i = 2; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vsldb: i = 2; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vstrcb: + case SystemZ::BI__builtin_s390_vstrch: + case SystemZ::BI__builtin_s390_vstrcf: + case SystemZ::BI__builtin_s390_vstrczb: + case SystemZ::BI__builtin_s390_vstrczh: + case SystemZ::BI__builtin_s390_vstrczf: + case SystemZ::BI__builtin_s390_vstrcbs: + case SystemZ::BI__builtin_s390_vstrchs: + case SystemZ::BI__builtin_s390_vstrcfs: + case SystemZ::BI__builtin_s390_vstrczbs: + case SystemZ::BI__builtin_s390_vstrczhs: + case SystemZ::BI__builtin_s390_vstrczfs: i = 3; l = 0; u = 15; break; + } + return SemaBuiltinConstantArgRange(TheCall, i, l, u); +} + bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break; + case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break; + case X86::BI__builtin_ia32_vpermil2pd: + case X86::BI__builtin_ia32_vpermil2pd256: + case X86::BI__builtin_ia32_vpermil2ps: + case X86::BI__builtin_ia32_vpermil2ps256: i = 3, l = 0; u = 3; break; + case X86::BI__builtin_ia32_cmpb128_mask: + case X86::BI__builtin_ia32_cmpw128_mask: + case X86::BI__builtin_ia32_cmpd128_mask: + case X86::BI__builtin_ia32_cmpq128_mask: + case X86::BI__builtin_ia32_cmpb256_mask: + case X86::BI__builtin_ia32_cmpw256_mask: + case X86::BI__builtin_ia32_cmpd256_mask: + case X86::BI__builtin_ia32_cmpq256_mask: + case X86::BI__builtin_ia32_cmpb512_mask: + case X86::BI__builtin_ia32_cmpw512_mask: + case X86::BI__builtin_ia32_cmpd512_mask: + case X86::BI__builtin_ia32_cmpq512_mask: + case X86::BI__builtin_ia32_ucmpb128_mask: + case X86::BI__builtin_ia32_ucmpw128_mask: + case X86::BI__builtin_ia32_ucmpd128_mask: + case X86::BI__builtin_ia32_ucmpq128_mask: + case X86::BI__builtin_ia32_ucmpb256_mask: + case X86::BI__builtin_ia32_ucmpw256_mask: + case X86::BI__builtin_ia32_ucmpd256_mask: + case X86::BI__builtin_ia32_ucmpq256_mask: + case X86::BI__builtin_ia32_ucmpb512_mask: + case X86::BI__builtin_ia32_ucmpw512_mask: + case X86::BI__builtin_ia32_ucmpd512_mask: + case X86::BI__builtin_ia32_ucmpq512_mask: i = 2; l = 0; u = 7; break; + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: i = 1, l = 0; u = 15; break; + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: i = 2, l = 0; u = 15; break; case X86::BI__builtin_ia32_cmpps: case X86::BI__builtin_ia32_cmpss: case X86::BI__builtin_ia32_cmppd: - case X86::BI__builtin_ia32_cmpsd: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_cmpsd: + case X86::BI__builtin_ia32_cmpps256: + case X86::BI__builtin_ia32_cmppd256: + case X86::BI__builtin_ia32_cmpps512_mask: + case X86::BI__builtin_ia32_cmppd512_mask: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_vpcomub: + case X86::BI__builtin_ia32_vpcomuw: + case X86::BI__builtin_ia32_vpcomud: + case X86::BI__builtin_ia32_vpcomuq: + case X86::BI__builtin_ia32_vpcomb: + case X86::BI__builtin_ia32_vpcomw: + case X86::BI__builtin_ia32_vpcomd: + case X86::BI__builtin_ia32_vpcomq: i = 2; l = 0; u = 7; break; } return SemaBuiltinConstantArgRange(TheCall, i, l, u); } @@ -1119,11 +1334,14 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, const FunctionProtoType *Proto) { - const VarDecl *V = dyn_cast<VarDecl>(NDecl); - if (!V) + QualType Ty; + if (const auto *V = dyn_cast<VarDecl>(NDecl)) + Ty = V->getType(); + else if (const auto *F = dyn_cast<FieldDecl>(NDecl)) + Ty = F->getType(); + else return false; - QualType Ty = V->getType(); if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType()) return false; @@ -1220,9 +1438,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // M is C if C is an integer, and ptrdiff_t if C is a pointer, and // the int parameters are for orderings. - assert(AtomicExpr::AO__c11_atomic_init == 0 && - AtomicExpr::AO__c11_atomic_fetch_xor + 1 == AtomicExpr::AO__atomic_load - && "need to update code for modified C11 atomics"); + static_assert(AtomicExpr::AO__c11_atomic_init == 0 && + AtomicExpr::AO__c11_atomic_fetch_xor + 1 == + AtomicExpr::AO__atomic_load, + "need to update code for modified C11 atomics"); bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init && Op <= AtomicExpr::AO__c11_atomic_fetch_xor; bool IsN = Op == AtomicExpr::AO__atomic_load_n || @@ -2039,7 +2258,7 @@ bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) { if (checkBuiltinArgument(*this, Call, 0)) return true; - static const struct { + const struct { unsigned ArgNo; QualType Type; } ArgumentTypes[] = { @@ -2286,7 +2505,7 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) { if (Arg->isInstantiationDependent()) return false; if (Arg->HasSideEffects(Context)) - return Diag(Arg->getLocStart(), diag::warn_assume_side_effects) + Diag(Arg->getLocStart(), diag::warn_assume_side_effects) << Arg->getSourceRange() << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier(); @@ -2603,6 +2822,8 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { .Case("strftime", FST_Strftime) .Case("strfmon", FST_Strfmon) .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) + .Case("freebsd_kprintf", FST_FreeBSDKPrintf) + .Case("os_trace", FST_OSTrace) .Default(FST_Unknown); } @@ -3073,10 +3294,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, if (InFunctionCall) { const Sema::SemaDiagnosticBuilder &D = S.Diag(Loc, PDiag); D << StringRange; - for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end(); - I != E; ++I) { - D << *I; - } + D << FixIt; } else { S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag) << ArgumentExpr->getSourceRange(); @@ -3086,10 +3304,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, diag::note_format_string_defined); Note << StringRange; - for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end(); - I != E; ++I) { - Note << *I; - } + Note << FixIt; } } @@ -3384,6 +3599,43 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier CoveredArgs.set(argIndex); } + // FreeBSD kernel extensions. + if (CS.getKind() == ConversionSpecifier::FreeBSDbArg || + CS.getKind() == ConversionSpecifier::FreeBSDDArg) { + // We need at least two arguments. + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1)) + return false; + + // Claim the second argument. + CoveredArgs.set(argIndex + 1); + + // Type check the first argument (int for %b, pointer for %D) + const Expr *Ex = getDataArg(argIndex); + const analyze_printf::ArgType &AT = + (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ? + ArgType(S.Context.IntTy) : ArgType::CPointerTy; + if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << Ex->getType() + << false << Ex->getSourceRange(), + Ex->getLocStart(), /*IsStringLocation*/false, + getSpecifierRange(startSpecifier, specifierLen)); + + // Type check the second argument (char * for both %b and %D) + Ex = getDataArg(argIndex + 1); + const analyze_printf::ArgType &AT2 = ArgType::CStrTy; + if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType())) + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_conversion_argument_type_mismatch) + << AT2.getRepresentativeTypeName(S.Context) << Ex->getType() + << false << Ex->getSourceRange(), + Ex->getLocStart(), /*IsStringLocation*/false, + getSpecifierRange(startSpecifier, specifierLen)); + + return true; + } + // Check for using an Objective-C specific conversion specifier // in a non-ObjC literal. if (!ObjCContext && CS.isObjCArg()) { @@ -3562,8 +3814,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ExprTy = TET->getUnderlyingExpr()->getType(); } - if (AT.matchesType(S.Context, ExprTy)) + analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy); + + if (match == analyze_printf::ArgType::Match) { return true; + } // Look through argument promotions for our error message's reported type. // This includes the integral and floating promotions, but excludes array @@ -3658,16 +3913,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen); if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) { + unsigned diag = diag::warn_format_conversion_argument_type_mismatch; + if (match == analyze_format_string::ArgType::NoMatchPedantic) { + diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; + } // In this case, the specifier is wrong and should be changed to match // the argument. - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum - << E->getSourceRange(), - E->getLocStart(), - /*IsStringLocation*/false, - SpecRange, - FixItHint::CreateReplacement(SpecRange, os.str())); + EmitFormatDiagnostic(S.PDiag(diag) + << AT.getRepresentativeTypeName(S.Context) + << IntendedTy << IsEnum << E->getSourceRange(), + E->getLocStart(), + /*IsStringLocation*/ false, SpecRange, + FixItHint::CreateReplacement(SpecRange, os.str())); } else { // The canonical type for formatting this value is different from the @@ -3741,15 +3998,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // arguments here. switch (S.isValidVarArgType(ExprTy)) { case Sema::VAK_Valid: - case Sema::VAK_ValidInCXX11: + case Sema::VAK_ValidInCXX11: { + unsigned diag = diag::warn_format_conversion_argument_type_mismatch; + if (match == analyze_printf::ArgType::NoMatchPedantic) { + diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; + } + EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); + S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy + << IsEnum << CSR << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/ false, CSR); break; - + } case Sema::VAK_Undefined: case Sema::VAK_MSVCUndefined: EmitFormatDiagnostic( @@ -3881,13 +4141,13 @@ bool CheckScanfHandler::HandleScanfSpecifier( FixItHint::CreateRemoval(R)); } } - + if (!FS.consumesDataArgument()) { // FIXME: Technically specifying a precision or field width here // makes no sense. Worth issuing a warning at some point. return true; } - + // Consume the argument. unsigned argIndex = FS.getArgIndex(); if (argIndex < NumDataArgs) { @@ -3896,7 +4156,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( // function if we encounter some other error. CoveredArgs.set(argIndex); } - + // Check the length modifier is valid with the given conversion specifier. if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo())) HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, @@ -3913,47 +4173,57 @@ bool CheckScanfHandler::HandleScanfSpecifier( // The remaining checks depend on the data arguments. if (HasVAListArg) return true; - + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) return false; - + // Check that the argument type matches the format specifier. const Expr *Ex = getDataArg(argIndex); if (!Ex) return true; 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(), - Ex->IgnoreImpCasts()->getType(), - S.getLangOpts(), S.Context); - - if (success) { - // Get the fix string from the fixed format specifier. - SmallString<128> buf; - llvm::raw_svector_ostream os(buf); - fixedFS.toString(os); - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false - << Ex->getSourceRange(), + if (!AT.isValid()) { + return true; + } + + analyze_format_string::ArgType::MatchKind match = + AT.matchesType(S.Context, Ex->getType()); + if (match == analyze_format_string::ArgType::Match) { + return true; + } + + ScanfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(), + S.getLangOpts(), S.Context); + + unsigned diag = diag::warn_format_conversion_argument_type_mismatch; + if (match == analyze_format_string::ArgType::NoMatchPedantic) { + diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; + } + + if (success) { + // Get the fix string from the fixed format specifier. + SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + EmitFormatDiagnostic( + S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) + << Ex->getType() << false << Ex->getSourceRange(), Ex->getLocStart(), - /*IsStringLocation*/false, + /*IsStringLocation*/ false, getSpecifierRange(startSpecifier, specifierLen), FixItHint::CreateReplacement( - getSpecifierRange(startSpecifier, specifierLen), - os.str())); - } else { - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false - << Ex->getSourceRange(), - Ex->getLocStart(), - /*IsStringLocation*/false, - getSpecifierRange(startSpecifier, specifierLen)); - } + getSpecifierRange(startSpecifier, specifierLen), os.str())); + } else { + EmitFormatDiagnostic(S.PDiag(diag) + << AT.getRepresentativeTypeName(S.Context) + << Ex->getType() << false << Ex->getSourceRange(), + Ex->getLocStart(), + /*IsStringLocation*/ false, + getSpecifierRange(startSpecifier, specifierLen)); } return true; @@ -4007,15 +4277,17 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, return; } - if (Type == FST_Printf || Type == FST_NSString) { + if (Type == FST_Printf || Type == FST_NSString || + Type == FST_FreeBSDKPrintf || Type == FST_OSTrace) { CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, - numDataArgs, (Type == FST_NSString), + numDataArgs, (Type == FST_NSString || Type == FST_OSTrace), Str, HasVAListArg, Args, format_idx, inFunctionCall, CallType, CheckedVarArgs); if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, getLangOpts(), - Context.getTargetInfo())) + Context.getTargetInfo(), + Type == FST_FreeBSDKPrintf)) H.DoneProcessing(); } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, @@ -4493,7 +4765,7 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T, /// \brief If E is a sizeof expression, returns its argument expression, /// otherwise returns NULL. -static const Expr *getSizeOfExprArg(const Expr* E) { +static const Expr *getSizeOfExprArg(const Expr *E) { if (const UnaryExprOrTypeTraitExpr *SizeOf = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType()) @@ -4503,7 +4775,7 @@ static const Expr *getSizeOfExprArg(const Expr* E) { } /// \brief If E is a sizeof expression, returns its argument type. -static QualType getSizeOfArgType(const Expr* E) { +static QualType getSizeOfArgType(const Expr *E) { if (const UnaryExprOrTypeTraitExpr *SizeOf = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) if (SizeOf->getKind() == clang::UETT_SizeOf) @@ -4549,8 +4821,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange(); QualType DestTy = Dest->getType(); + QualType PointeeTy; if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { - QualType PointeeTy = DestPtrTy->getPointeeType(); + PointeeTy = DestPtrTy->getPointeeType(); // Never warn about void type pointers. This can be used to suppress // false positives. @@ -4630,47 +4903,53 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, break; } } + } else if (DestTy->isArrayType()) { + PointeeTy = DestTy; + } - // Always complain about dynamic classes. - bool IsContained; - if (const CXXRecordDecl *ContainedRD = - getContainedDynamicClass(PointeeTy, IsContained)) { - - unsigned OperationType = 0; - // "overwritten" if we're warning about the destination for any call - // but memcmp; otherwise a verb appropriate to the call. - if (ArgIdx != 0 || BId == Builtin::BImemcmp) { - if (BId == Builtin::BImemcpy) - OperationType = 1; - else if(BId == Builtin::BImemmove) - OperationType = 2; - else if (BId == Builtin::BImemcmp) - OperationType = 3; - } - - DiagRuntimeBehavior( - Dest->getExprLoc(), Dest, - PDiag(diag::warn_dyn_class_memaccess) - << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) - << FnName << IsContained << ContainedRD << OperationType - << Call->getCallee()->getSourceRange()); - } else if (PointeeTy.hasNonTrivialObjCLifetime() && - BId != Builtin::BImemset) - DiagRuntimeBehavior( - Dest->getExprLoc(), Dest, - PDiag(diag::warn_arc_object_memaccess) - << ArgIdx << FnName << PointeeTy - << Call->getCallee()->getSourceRange()); - else - continue; + if (PointeeTy == QualType()) + continue; + // Always complain about dynamic classes. + bool IsContained; + if (const CXXRecordDecl *ContainedRD = + getContainedDynamicClass(PointeeTy, IsContained)) { + + unsigned OperationType = 0; + // "overwritten" if we're warning about the destination for any call + // but memcmp; otherwise a verb appropriate to the call. + if (ArgIdx != 0 || BId == Builtin::BImemcmp) { + if (BId == Builtin::BImemcpy) + OperationType = 1; + else if(BId == Builtin::BImemmove) + OperationType = 2; + else if (BId == Builtin::BImemcmp) + OperationType = 3; + } + DiagRuntimeBehavior( Dest->getExprLoc(), Dest, - PDiag(diag::note_bad_memaccess_silence) - << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); - break; - } + PDiag(diag::warn_dyn_class_memaccess) + << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) + << FnName << IsContained << ContainedRD << OperationType + << Call->getCallee()->getSourceRange()); + } else if (PointeeTy.hasNonTrivialObjCLifetime() && + BId != Builtin::BImemset) + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_arc_object_memaccess) + << ArgIdx << FnName << PointeeTy + << Call->getCallee()->getSourceRange()); + else + continue; + + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::note_bad_memaccess_silence) + << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); + break; } + } // A little helper routine: ignore addition and subtraction of integer literals. @@ -5821,7 +6100,7 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, // TODO: Investigate using GetExprRange() to get tighter bounds // on the bit ranges. QualType OtherT = Other->getType(); - if (const AtomicType *AT = dyn_cast<AtomicType>(OtherT)) + if (const auto *AT = OtherT->getAs<AtomicType>()) OtherT = AT->getValueType(); IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); unsigned OtherWidth = OtherRange.Width; @@ -6665,8 +6944,11 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { E = POE->getResultExpr(); } - if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) - return AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { + if (OVE->getSourceExpr()) + AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); + return; + } // Skip past explicit casts. if (isa<ExplicitCastExpr>(E)) { @@ -6748,7 +7030,7 @@ static bool CheckForReference(Sema &SemaRef, const Expr *E, if (!M->getMemberDecl()->getType()->isReferenceType()) return false; } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) { - if (!Call->getCallReturnType()->isReferenceType()) + if (!Call->getCallReturnType(SemaRef.Context)->isReferenceType()) return false; FD = Call->getDirectCallee(); } else { @@ -7493,6 +7775,35 @@ void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc); } +static void diagnoseArrayStarInParamType(Sema &S, QualType PType, + SourceLocation Loc) { + if (!PType->isVariablyModifiedType()) + return; + if (const auto *PointerTy = dyn_cast<PointerType>(PType)) { + diagnoseArrayStarInParamType(S, PointerTy->getPointeeType(), Loc); + return; + } + if (const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) { + diagnoseArrayStarInParamType(S, ReferenceTy->getPointeeType(), Loc); + return; + } + if (const auto *ParenTy = dyn_cast<ParenType>(PType)) { + diagnoseArrayStarInParamType(S, ParenTy->getInnerType(), Loc); + return; + } + + const ArrayType *AT = S.Context.getAsArrayType(PType); + if (!AT) + return; + + if (AT->getSizeModifier() != ArrayType::Star) { + diagnoseArrayStarInParamType(S, AT->getElementType(), Loc); + return; + } + + S.Diag(Loc, diag::err_array_star_in_function_definition); +} + /// CheckParmsForFunctionDef - Check that the parameters of the given /// function are appropriate for the definition of a function. This /// takes care of any checks that cannot be performed on the @@ -7531,15 +7842,9 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, // notation in their sequences of declarator specifiers to specify // variable length array types. QualType PType = Param->getOriginalType(); - while (const ArrayType *AT = Context.getAsArrayType(PType)) { - if (AT->getSizeModifier() == ArrayType::Star) { - // FIXME: This diagnostic should point the '[*]' if source-location - // information is added for it. - Diag(Param->getLocation(), diag::err_array_star_in_function_definition); - break; - } - PType= AT->getElementType(); - } + // FIXME: This diagnostic should point the '[*]' if source-location + // information is added for it. + diagnoseArrayStarInParamType(*this, PType, Param->getLocation()); // MSVC destroys objects passed by value in the callee. Therefore a // function definition which takes such a parameter must be able to call the @@ -8057,6 +8362,236 @@ static bool isSetterLikeSelector(Selector sel) { return !isLowercase(str.front()); } +static Optional<int> GetNSMutableArrayArgumentIndex(Sema &S, + ObjCMessageExpr *Message) { + if (S.NSMutableArrayPointer.isNull()) { + IdentifierInfo *NSMutableArrayId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableArray); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableArrayId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!InterfaceDecl) { + return None; + } + QualType NSMutableArrayObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableArrayPointer = + S.Context.getObjCObjectPointerType(NSMutableArrayObject); + } + + if (S.NSMutableArrayPointer != Message->getReceiverType()) { + return None; + } + + Selector Sel = Message->getSelector(); + + Optional<NSAPI::NSArrayMethodKind> MKOpt = + S.NSAPIObj->getNSArrayMethodKind(Sel); + if (!MKOpt) { + return None; + } + + NSAPI::NSArrayMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableArr_addObject: + case NSAPI::NSMutableArr_insertObjectAtIndex: + case NSAPI::NSMutableArr_setObjectAtIndexedSubscript: + return 0; + case NSAPI::NSMutableArr_replaceObjectAtIndex: + return 1; + + default: + return None; + } + + return None; +} + +static +Optional<int> GetNSMutableDictionaryArgumentIndex(Sema &S, + ObjCMessageExpr *Message) { + + if (S.NSMutableDictionaryPointer.isNull()) { + IdentifierInfo *NSMutableDictionaryId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableDictionary); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableDictionaryId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!InterfaceDecl) { + return None; + } + QualType NSMutableDictionaryObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableDictionaryPointer = + S.Context.getObjCObjectPointerType(NSMutableDictionaryObject); + } + + if (S.NSMutableDictionaryPointer != Message->getReceiverType()) { + return None; + } + + Selector Sel = Message->getSelector(); + + Optional<NSAPI::NSDictionaryMethodKind> MKOpt = + S.NSAPIObj->getNSDictionaryMethodKind(Sel); + if (!MKOpt) { + return None; + } + + NSAPI::NSDictionaryMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableDict_setObjectForKey: + case NSAPI::NSMutableDict_setValueForKey: + case NSAPI::NSMutableDict_setObjectForKeyedSubscript: + return 0; + + default: + return None; + } + + return None; +} + +static Optional<int> GetNSSetArgumentIndex(Sema &S, ObjCMessageExpr *Message) { + + ObjCInterfaceDecl *InterfaceDecl; + if (S.NSMutableSetPointer.isNull()) { + IdentifierInfo *NSMutableSetId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableSet); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableSetId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (InterfaceDecl) { + QualType NSMutableSetObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableSetPointer = + S.Context.getObjCObjectPointerType(NSMutableSetObject); + } + } + + if (S.NSCountedSetPointer.isNull()) { + IdentifierInfo *NSCountedSetId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSCountedSet); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSCountedSetId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (InterfaceDecl) { + QualType NSCountedSetObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSCountedSetPointer = + S.Context.getObjCObjectPointerType(NSCountedSetObject); + } + } + + if (S.NSMutableOrderedSetPointer.isNull()) { + IdentifierInfo *NSOrderedSetId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableOrderedSet); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSOrderedSetId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (InterfaceDecl) { + QualType NSOrderedSetObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableOrderedSetPointer = + S.Context.getObjCObjectPointerType(NSOrderedSetObject); + } + } + + QualType ReceiverType = Message->getReceiverType(); + + bool IsMutableSet = !S.NSMutableSetPointer.isNull() && + ReceiverType == S.NSMutableSetPointer; + bool IsMutableOrderedSet = !S.NSMutableOrderedSetPointer.isNull() && + ReceiverType == S.NSMutableOrderedSetPointer; + bool IsCountedSet = !S.NSCountedSetPointer.isNull() && + ReceiverType == S.NSCountedSetPointer; + + if (!IsMutableSet && !IsMutableOrderedSet && !IsCountedSet) { + return None; + } + + Selector Sel = Message->getSelector(); + + Optional<NSAPI::NSSetMethodKind> MKOpt = S.NSAPIObj->getNSSetMethodKind(Sel); + if (!MKOpt) { + return None; + } + + NSAPI::NSSetMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableSet_addObject: + case NSAPI::NSOrderedSet_setObjectAtIndex: + case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript: + case NSAPI::NSOrderedSet_insertObjectAtIndex: + return 0; + case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject: + return 1; + } + + return None; +} + +void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) { + if (!Message->isInstanceMessage()) { + return; + } + + Optional<int> ArgOpt; + + if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) && + !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) && + !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) { + return; + } + + int ArgIndex = *ArgOpt; + + Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts(); + if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) { + Receiver = OE->getSourceExpr()->IgnoreImpCasts(); + } + + Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts(); + if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) { + Arg = OE->getSourceExpr()->IgnoreImpCasts(); + } + + if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) { + if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) { + if (ReceiverRE->getDecl() == ArgRE->getDecl()) { + ValueDecl *Decl = ReceiverRE->getDecl(); + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << Decl->getName(); + Diag(Decl->getLocation(), + diag::note_objc_circular_container_declared_here) + << Decl->getName(); + } + } + } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) { + if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) { + if (IvarRE->getDecl() == IvarArgRE->getDecl()) { + ObjCIvarDecl *Decl = IvarRE->getDecl(); + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << Decl->getName(); + Diag(Decl->getLocation(), + diag::note_objc_circular_container_declared_here) + << Decl->getName(); + } + } + } + +} + /// Check a message send to see if it's likely to cause a retain cycle. void Sema::checkRetainCycles(ObjCMessageExpr *msg) { // Only check instance methods whose selector looks like a setter. @@ -8241,7 +8776,7 @@ bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, // Get line numbers of statement and body. bool StmtLineInvalid; - unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc, + unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc, &StmtLineInvalid); if (StmtLineInvalid) return false; |