void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc,
bool isObjCMethod = false,
- const AttrVec *Attrs = 0);
+ const AttrVec *Attrs = 0,
+ const FunctionDecl *FD = 0);
void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS);
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
}
bool Result;
- if (Expr->EvaluateAsBooleanCondition(Result, S.Context) && !Result)
- return true;
-
- return false;
+ return (!Expr->isValueDependent() &&
+ Expr->EvaluateAsBooleanCondition(Result, S.Context) &&
+ !Result);
}
static void CheckNonNullArgument(Sema &S,
Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc,
bool isObjCMethod,
- const AttrVec *Attrs) {
+ const AttrVec *Attrs,
+ const FunctionDecl *FD) {
CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc);
// Check if the return value is null but should not be.
<< (isObjCMethod ? 1 : 0) << RetValExp->getSourceRange();
break;
}
+
+ // C++11 [basic.stc.dynamic.allocation]p4:
+ // If an allocation function declared with a non-throwing
+ // exception-specification fails to allocate storage, it shall return
+ // a null pointer. Any other allocation function that fails to allocate
+ // storage shall indicate failure only by throwing an exception [...]
+ if (FD) {
+ OverloadedOperatorKind Op = FD->getOverloadedOperator();
+ if (Op == OO_New || Op == OO_Array_New) {
+ const FunctionProtoType *Proto
+ = FD->getType()->castAs<FunctionProtoType>();
+ if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) &&
+ CheckNonNullExpr(*this, RetValExp))
+ Diag(ReturnLoc, diag::warn_operator_new_returns_null)
+ << FD << getLangOpts().CPlusPlus11;
+ }
+ }
}
//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
RetValExp = Res.takeAs<Expr>();
}
- CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc, isObjCMethod, Attrs);
-
- // C++11 [basic.stc.dynamic.allocation]p4:
- // If an allocation function declared with a non-throwing
- // exception-specification fails to allocate storage, it shall return
- // a null pointer. Any other allocation function that fails to allocate
- // storage shall indicate failure only by throwing an exception [...]
- if (const FunctionDecl *FD = getCurFunctionDecl()) {
- OverloadedOperatorKind Op = FD->getOverloadedOperator();
- if (Op == OO_New || Op == OO_Array_New) {
- const FunctionProtoType *Proto
- = FD->getType()->castAs<FunctionProtoType>();
- bool ReturnValueNonNull;
-
- if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) &&
- !RetValExp->isValueDependent() &&
- RetValExp->EvaluateAsBooleanCondition(ReturnValueNonNull,
- Context) &&
- !ReturnValueNonNull)
- Diag(ReturnLoc, diag::warn_operator_new_returns_null)
- << FD << getLangOpts().CPlusPlus11;
- }
- }
+ CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc, isObjCMethod, Attrs,
+ getCurFunctionDecl());
}
if (RetValExp) {
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<int I>
+struct TS {
+ __attribute__((returns_nonnull))
+ void *value_dependent(void) {
+ return I; // no-warning
+ }
+
+ __attribute__((returns_nonnull))
+ void *value_independent(void) {
+ return 0; // expected-warning {{null returned from function that requires a non-null return value}}
+ }
+};
+