summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp781
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;