When analyzing for member self-assignment, don't attempt to dereference null

Stmt* such as those which occur in ?: . Fixes PR7378.

Also, generally whip the code into shape fixing several coding style violations.

llvm-svn: 105992
This commit is contained in:
Nick Lewycky 2010-06-15 07:32:55 +00:00
parent a55b8877e6
commit a2fb98bfda
1 changed files with 21 additions and 19 deletions

View File

@ -1217,18 +1217,25 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
/// containing the field that is being initialized. Returns true if there is an
/// uninitialized field was used an updates the SourceLocation parameter; false
/// otherwise.
static bool InitExprContainsUninitializedFields(const Stmt* S,
const FieldDecl* LhsField,
SourceLocation* L) {
const MemberExpr* ME = dyn_cast<MemberExpr>(S);
if (ME) {
const NamedDecl* RhsField = ME->getMemberDecl();
static bool InitExprContainsUninitializedFields(const Stmt *S,
const FieldDecl *LhsField,
SourceLocation *L) {
if (isa<CallExpr>(S)) {
// Do not descend into function calls or constructors, as the use
// of an uninitialized field may be valid. One would have to inspect
// the contents of the function/ctor to determine if it is safe or not.
// i.e. Pass-by-value is never safe, but pass-by-reference and pointers
// may be safe, depending on what the function/ctor does.
return false;
}
if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
const NamedDecl *RhsField = ME->getMemberDecl();
if (RhsField == LhsField) {
// Initializing a field with itself. Throw a warning.
// But wait; there are exceptions!
// Exception #1: The field may not belong to this record.
// e.g. Foo(const Foo& rhs) : A(rhs.A) {}
const Expr* base = ME->getBase();
const Expr *base = ME->getBase();
if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
// Even though the field matches, it does not belong to this record.
return false;
@ -1239,21 +1246,16 @@ static bool InitExprContainsUninitializedFields(const Stmt* S,
return true;
}
}
bool found = false;
for (Stmt::const_child_iterator it = S->child_begin();
it != S->child_end() && found == false;
++it) {
if (isa<CallExpr>(S)) {
// Do not descend into function calls or constructors, as the use
// of an uninitialized field may be valid. One would have to inspect
// the contents of the function/ctor to determine if it is safe or not.
// i.e. Pass-by-value is never safe, but pass-by-reference and pointers
// may be safe, depending on what the function/ctor does.
for (Stmt::const_child_iterator it = S->child_begin(), e = S->child_end();
it != e; ++it) {
if (!*it) {
// An expression such as 'member(arg ?: "")' may trigger this.
continue;
}
found = InitExprContainsUninitializedFields(*it, LhsField, L);
if (InitExprContainsUninitializedFields(*it, LhsField, L))
return true;
}
return found;
return false;
}
Sema::MemInitResult