summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp406
1 files changed, 231 insertions, 175 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 65b57c3..415ab3f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -76,12 +76,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
}
// See if this is an auto-typed variable whose initializer we are parsing.
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->isParsingAutoInit()) {
- Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName();
- return true;
- }
+ if (ParsingInitForAutoVars.count(D)) {
+ Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+ << D->getDeclName();
+ return true;
}
// See if the decl is deprecated.
@@ -389,13 +387,13 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
return false;
if (Expr->getType()->isObjCObjectType() &&
- DiagRuntimeBehavior(Expr->getLocStart(),
+ DiagRuntimeBehavior(Expr->getLocStart(), 0,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Expr->getType() << CT))
return true;
if (!Expr->getType()->isPODType() &&
- DiagRuntimeBehavior(Expr->getLocStart(),
+ DiagRuntimeBehavior(Expr->getLocStart(), 0,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< Expr->getType() << CT))
return true;
@@ -1675,20 +1673,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// This is guaranteed from this point on.
assert(!R.empty() || ADL);
- if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
- if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp &&
- !(getLangOptions().ObjCDefaultSynthProperties &&
- getLangOptions().ObjCNonFragileABI2) &&
- Var->isFileVarDecl()) {
- ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II);
- if (Property) {
- Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName();
- Diag(Property->getLocation(), diag::note_property_declare);
- Diag(Var->getLocation(), diag::note_global_declared_at);
- }
- }
- }
-
// Check whether this might be a C++ implicit instance member access.
// C++ [class.mfct.non-static]p3:
// When an id-expression that is not part of a class member access
@@ -3996,131 +3980,130 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Failure cases.
fail:
- // There's a possible road to recovery for function types.
- const FunctionType *Fun = 0;
- SourceLocation ParenInsertionLoc =
- PP.getLocForEndOfToken(BaseExpr->getLocEnd());
-
+ // Recover from dot accesses to pointers, e.g.:
+ // type *foo;
+ // foo.bar
+ // This is actually well-formed in two cases:
+ // - 'type' is an Objective C type
+ // - 'bar' is a pseudo-destructor name which happens to refer to
+ // the appropriate pointer type
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
- if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
- // fall out, handled below.
-
- // Recover from dot accesses to pointers, e.g.:
- // type *foo;
- // foo.bar
- // This is actually well-formed in two cases:
- // - 'type' is an Objective C type
- // - 'bar' is a pseudo-destructor name which happens to refer to
- // the appropriate pointer type
- } else if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
- MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
+ if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
+ MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
- << FixItHint::CreateReplacement(OpLoc, "->");
+ << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, "->");
// Recurse as an -> access.
IsArrow = true;
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
- } else {
- Fun = BaseType->getAs<FunctionType>();
- }
-
- // If the user is trying to apply -> or . to a function pointer
- // type, it's probably because they forgot parentheses to call that
- // function. Suggest the addition of those parentheses, build the
- // call, and continue on.
- if (Fun || BaseType == Context.OverloadTy) {
- bool TryCall;
- if (BaseType == Context.OverloadTy) {
- // Plunder the overload set for something that would make the member
- // expression valid.
- const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr);
- UnresolvedSet<4> CandidateOverloads;
- bool HasZeroArgCandidateOverload = false;
- for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
- DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
- const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
- QualType ResultTy = OverloadDecl->getResultType();
- if ((!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getPointeeType()->isRecordType())) {
- CandidateOverloads.addDecl(*it);
- if (OverloadDecl->getNumParams() == 0) {
- HasZeroArgCandidateOverload = true;
- }
+ }
+
+ // If the user is trying to apply -> or . to a function name, it's probably
+ // because they forgot parentheses to call that function.
+ bool TryCall = false;
+ bool Overloaded = false;
+ UnresolvedSet<8> AllOverloads;
+ if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr)) {
+ AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end());
+ TryCall = true;
+ Overloaded = true;
+ } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr)) {
+ if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
+ AllOverloads.addDecl(Fun);
+ TryCall = true;
+ }
+ }
+
+ if (TryCall) {
+ // Plunder the overload set for something that would make the member
+ // expression valid.
+ UnresolvedSet<4> ViableOverloads;
+ bool HasViableZeroArgOverload = false;
+ for (OverloadExpr::decls_iterator it = AllOverloads.begin(),
+ DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) {
+ const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
+ QualType ResultTy = OverloadDecl->getResultType();
+ if ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType())) {
+ ViableOverloads.addDecl(*it);
+ if (OverloadDecl->getMinRequiredArguments() == 0) {
+ HasViableZeroArgOverload = true;
}
}
- if (HasZeroArgCandidateOverload && CandidateOverloads.size() == 1) {
- // We have one reasonable overload, and there's only one way to call it,
- // so emit a fixit and try to recover
- Diag(ParenInsertionLoc, diag::err_member_reference_needs_call)
- << 1
- << BaseExpr->getSourceRange()
- << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
- TryCall = true;
- } else {
- Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
- << 0
- << BaseExpr->getSourceRange();
- int CandidateOverloadCount = CandidateOverloads.size();
- int I;
- for (I = 0; I < CandidateOverloadCount; ++I) {
- // FIXME: Magic number for max shown overloads stolen from
- // OverloadCandidateSet::NoteCandidates.
- if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
- break;
- }
- Diag(CandidateOverloads[I].getDecl()->getSourceRange().getBegin(),
- diag::note_member_ref_possible_intended_overload);
- }
- if (I != CandidateOverloadCount) {
- Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
- << int(CandidateOverloadCount - I);
+ }
+
+ if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) {
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << 1 << 0
+ << BaseExpr->getSourceRange();
+ int ViableOverloadCount = ViableOverloads.size();
+ int I;
+ for (I = 0; I < ViableOverloadCount; ++I) {
+ // FIXME: Magic number for max shown overloads stolen from
+ // OverloadCandidateSet::NoteCandidates.
+ if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
+ break;
}
- return ExprError();
+ Diag(ViableOverloads[I].getDecl()->getSourceRange().getBegin(),
+ diag::note_member_ref_possible_intended_overload);
}
- } else {
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
- TryCall = (FPT->getNumArgs() == 0);
- } else {
- TryCall = true;
+ if (I != ViableOverloadCount) {
+ Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
+ << int(ViableOverloadCount - I);
}
-
- if (TryCall) {
- QualType ResultTy = Fun->getResultType();
- TryCall = (!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getAs<PointerType>()->getPointeeType()->isRecordType());
+ return ExprError();
+ }
+ } else {
+ // We don't have an expression that's convenient to get a Decl from, but we
+ // can at least check if the type is "function of 0 arguments which returns
+ // an acceptable type".
+ const FunctionType *Fun = NULL;
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+ if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
+ TryCall = true;
}
+ } else if ((Fun = BaseType->getAs<FunctionType>())) {
+ TryCall = true;
}
-
if (TryCall) {
- if (Fun) {
- Diag(BaseExpr->getExprLoc(),
- diag::err_member_reference_needs_call_zero_arg)
- << QualType(Fun, 0)
- << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
+ if (FPT->getNumArgs() == 0) {
+ QualType ResultTy = Fun->getResultType();
+ TryCall = (!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType());
+ }
}
-
- ExprResult NewBase
- = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
- MultiExprArg(*this, 0, 0), ParenInsertionLoc);
- if (NewBase.isInvalid())
- return ExprError();
- BaseExpr = NewBase.takeAs<Expr>();
-
-
- DefaultFunctionArrayConversion(BaseExpr);
- BaseType = BaseExpr->getType();
-
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
}
}
+ if (TryCall) {
+ // At this point, we know BaseExpr looks like it's potentially callable with
+ // 0 arguments, and that it returns something of a reasonable type, so we
+ // can emit a fixit and carry on pretending that BaseExpr was actually a
+ // CallExpr.
+ SourceLocation ParenInsertionLoc =
+ PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << int(Overloaded) << 1
+ << BaseExpr->getSourceRange()
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
+ MultiExprArg(*this, 0, 0),
+ ParenInsertionLoc);
+ if (NewBase.isInvalid())
+ return ExprError();
+ BaseExpr = NewBase.takeAs<Expr>();
+ DefaultFunctionArrayConversion(BaseExpr);
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ }
+
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
<< BaseType << BaseExpr->getSourceRange();
@@ -4298,6 +4281,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
const FunctionProtoType *Proto,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc) {
+ // Bail out early if calling a builtin with custom typechecking.
+ // We don't need to do this in the
+ if (FDecl)
+ if (unsigned ID = FDecl->getBuiltinID())
+ if (Context.BuiltinInfo.hasCustomTypechecking(ID))
+ return false;
+
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
unsigned NumArgsInProto = Proto->getNumArgs();
@@ -4625,22 +4615,41 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
RParenLoc);
}
+ unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
+
+ // Bail out early if calling a builtin with custom typechecking.
+ if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
+ return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+
const FunctionType *FuncT;
- if (!Fn->getType()->isBlockPointerType()) {
+ if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
// have type pointer to function".
- const PointerType *PT = Fn->getType()->getAs<PointerType>();
- if (PT == 0)
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
FuncT = PT->getPointeeType()->getAs<FunctionType>();
- } else { // This is a block call.
- FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()->
- getAs<FunctionType>();
- }
- if (FuncT == 0)
+ if (FuncT == 0)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ } else if (const BlockPointerType *BPT =
+ Fn->getType()->getAs<BlockPointerType>()) {
+ FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+ } else {
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
+ }
+
+ if (getLangOptions().CUDA) {
+ if (Config) {
+ // CUDA: Kernel calls must be to global functions
+ if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
+ return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
+ << FDecl->getName() << Fn->getSourceRange());
+
+ // CUDA: Kernel function must have 'void' return type
+ if (!FuncT->getResultType()->isVoidType())
+ return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
+ << Fn->getType() << Fn->getSourceRange());
+ }
+ }
// Check for a valid return type
if (CheckCallReturnType(FuncT->getResultType(),
@@ -4721,7 +4730,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (CheckFunctionCall(FDecl, TheCall))
return ExprError();
- if (unsigned BuiltinID = FDecl->getBuiltinID())
+ if (BuiltinID)
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
if (CheckBlockCall(NDecl, TheCall))
@@ -6372,8 +6381,8 @@ QualType Sema::CheckMultiplyDivideOperands(
// Check for division by zero.
if (isDiv &&
rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_division_by_zero)
- << rex->getSourceRange());
+ DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero)
+ << rex->getSourceRange());
return compType;
}
@@ -6394,8 +6403,8 @@ QualType Sema::CheckRemainderOperands(
// Check for remainder by zero.
if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_remainder_by_zero)
- << rex->getSourceRange());
+ DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero)
+ << rex->getSourceRange());
return compType;
}
@@ -6629,9 +6638,61 @@ static bool isScopedEnumerationType(QualType T) {
return false;
}
+static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex,
+ SourceLocation Loc, unsigned Opc,
+ QualType LHSTy) {
+ llvm::APSInt Right;
+ // Check right/shifter operand
+ if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context))
+ return;
+
+ if (Right.isNegative()) {
+ S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
+ return;
+ }
+ llvm::APInt LeftBits(Right.getBitWidth(),
+ S.Context.getTypeSize(lex->getType()));
+ if (Right.uge(LeftBits)) {
+ S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
+ return;
+ }
+ if (Opc != BO_Shl)
+ return;
+
+ // When left shifting an ICE which is signed, we can check for overflow which
+ // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
+ // integers have defined behavior modulo one more than the maximum value
+ // representable in the result type, so never warn for those.
+ llvm::APSInt Left;
+ if (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) ||
+ LHSTy->hasUnsignedIntegerRepresentation())
+ return;
+ llvm::APInt ResultBits =
+ static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
+ if (LeftBits.uge(ResultBits))
+ return;
+ llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue());
+ Result = Result.shl(Right);
+
+ // If we are only missing a sign bit, this is less likely to result in actual
+ // bugs -- if the result is cast back to an unsigned type, it will have the
+ // expected value. Thus we place this behind a different warning that can be
+ // turned off separately if needed.
+ if (LeftBits == ResultBits - 1) {
+ S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit)
+ << Result.toString(10) << LHSTy
+ << lex->getSourceRange() << rex->getSourceRange();
+ return;
+ }
+
+ S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
+ << Result.toString(10) << Result.getMinSignedBits() << LHSTy
+ << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange();
+}
+
// C99 6.5.7
QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
- bool isCompAssign) {
+ unsigned Opc, bool isCompAssign) {
// C99 6.5.7p2: Each of the operands shall have integer type.
if (!lex->getType()->hasIntegerRepresentation() ||
!rex->getType()->hasIntegerRepresentation())
@@ -6662,19 +6723,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
UsualUnaryConversions(rex);
// Sanity-check shift operands
- llvm::APSInt Right;
- // Check right/shifter operand
- if (!rex->isValueDependent() &&
- rex->isIntegerConstantExpr(Right, Context)) {
- if (Right.isNegative())
- Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
- else {
- llvm::APInt LeftBits(Right.getBitWidth(),
- Context.getTypeSize(lex->getType()));
- if (Right.uge(LeftBits))
- Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
- }
- }
+ DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy);
// "The type of the result is that of the promoted left operand."
return LHSTy;
@@ -6738,7 +6787,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
if (DRL->getDecl() == DRR->getDecl() &&
!IsWithinTemplateSpecialization(DRL->getDecl())) {
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
|| Opc == BO_LE
@@ -6760,7 +6809,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
always_evals_to = 2; // e.g. array1 <= array2
break;
}
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 1 // array
<< always_evals_to);
}
@@ -6801,7 +6850,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
default: assert(false && "Invalid comparison operator");
}
- DiagRuntimeBehavior(Loc,
+ DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange());
@@ -7111,7 +7160,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc,
+ DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_comparison_always)
<< 0 // self-
<< 2 // "a constant"
@@ -7372,9 +7421,11 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
- Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null)
- << UO->getSubExpr()->getSourceRange();
- Diag(UO->getOperatorLoc(), diag::note_indirection_through_null);
+ DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ PDiag(diag::warn_indirection_through_null)
+ << UO->getSubExpr()->getSourceRange());
+ DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ PDiag(diag::note_indirection_through_null));
}
// Check for trivial buffer overflows.
@@ -7959,7 +8010,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_Shl:
case BO_Shr:
- ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
+ ResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc);
break;
case BO_LE:
case BO_LT:
@@ -8006,7 +8057,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_ShlAssign:
case BO_ShrAssign:
- CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+ CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
@@ -8563,7 +8614,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// (clause 9).
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc,
+ DiagRuntimeBehavior(BuiltinLoc, 0,
PDiag(diag::warn_offsetof_non_pod_type)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< CurrentType))
@@ -8907,12 +8958,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
- // Issue any analysis-based warnings.
- const sema::AnalysisBasedWarnings::Policy &WP =
- AnalysisWarnings.getDefaultPolicy();
- AnalysisWarnings.IssueWarnings(WP, Result);
-
- PopFunctionOrBlockScope();
+ const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
+ PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
return Owned(Result);
}
@@ -9350,9 +9397,12 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
}
}
- // Keep track of used but undefined variables.
+ // Keep track of used but undefined variables. We make a hole in
+ // the warning for static const data members with in-line
+ // initializers.
if (Var->hasDefinition() == VarDecl::DeclarationOnly
- && Var->getLinkage() != ExternalLinkage) {
+ && Var->getLinkage() != ExternalLinkage
+ && !(Var->isStaticDataMember() && Var->hasInit())) {
SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
if (old.isInvalid()) old = Loc;
}
@@ -9484,7 +9534,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E) {
/// behavior of a program, such as passing a non-POD value through an ellipsis.
/// Failure to do so will likely result in spurious diagnostics or failures
/// during overload resolution or within sizeof/alignof/typeof/typeid.
-bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt,
const PartialDiagnostic &PD) {
switch (ExprEvalContexts.back().Context ) {
case Unevaluated:
@@ -9493,7 +9543,13 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
case PotentiallyEvaluated:
case PotentiallyEvaluatedIfUsed:
- Diag(Loc, PD);
+ if (stmt && getCurFunctionOrMethodDecl()) {
+ FunctionScopes.back()->PossiblyUnreachableDiags.
+ push_back(sema::PossiblyUnreachableDiag(PD, Loc, stmt));
+ }
+ else
+ Diag(Loc, PD);
+
return true;
case PotentiallyPotentiallyEvaluated:
OpenPOWER on IntegriCloud