Kaydet (Commit) acd8f0c3 authored tarafından Noel Grandin's avatar Noel Grandin

fix some crashes in unusedfields plugin

for some reason the insideMoveOrCopyDecl pointer to MethodDecl becomes
bad during AST traversal, but the pointers to RecordDecl seem stable?

Change-Id: Ida939f5ca4780e674b245411f7395f147258544e
üst fb37189e
......@@ -84,8 +84,9 @@ public:
bool TraverseCXXMethodDecl( CXXMethodDecl* );
private:
MyFieldInfo niceName(const FieldDecl*);
void checkTouched(const FieldDecl* fieldDecl, const Expr* memberExpr);
CXXMethodDecl * insideMoveOrCopyDecl;
void checkTouchedFromOutside(const FieldDecl* fieldDecl, const Expr* memberExpr);
void checkWriteOnly(const FieldDecl* fieldDecl, const Expr* memberExpr);
RecordDecl * insideMoveOrCopyDeclParent;
};
void UnusedFields::run()
......@@ -200,19 +201,21 @@ bool startswith(const std::string& rStr, const char* pSubStr)
bool UnusedFields::TraverseCXXConstructorDecl(CXXConstructorDecl* cxxConstructorDecl)
{
if (cxxConstructorDecl->isCopyOrMoveConstructor())
insideMoveOrCopyDecl = cxxConstructorDecl;
if (!ignoreLocation(cxxConstructorDecl)
&& cxxConstructorDecl->isCopyOrMoveConstructor())
insideMoveOrCopyDeclParent = cxxConstructorDecl->getParent();
bool ret = RecursiveASTVisitor::TraverseCXXConstructorDecl(cxxConstructorDecl);
insideMoveOrCopyDecl = nullptr;
insideMoveOrCopyDeclParent = nullptr;
return ret;
}
bool UnusedFields::TraverseCXXMethodDecl(CXXMethodDecl* cxxMethodDecl)
{
if (cxxMethodDecl->isCopyAssignmentOperator() || cxxMethodDecl->isMoveAssignmentOperator())
insideMoveOrCopyDecl = cxxMethodDecl;
if (!ignoreLocation(cxxMethodDecl)
&& (cxxMethodDecl->isCopyAssignmentOperator() || cxxMethodDecl->isMoveAssignmentOperator()))
insideMoveOrCopyDeclParent = cxxMethodDecl->getParent();
bool ret = RecursiveASTVisitor::TraverseCXXMethodDecl(cxxMethodDecl);
insideMoveOrCopyDecl = nullptr;
insideMoveOrCopyDeclParent = nullptr;
return ret;
}
......@@ -232,21 +235,21 @@ bool UnusedFields::VisitMemberExpr( const MemberExpr* memberExpr )
return true;
}
MyFieldInfo fieldInfo = niceName(fieldDecl);
// for the touched-from-outside analysis
checkTouchedFromOutside(fieldDecl, memberExpr);
checkTouched(fieldDecl, memberExpr);
checkWriteOnly(fieldDecl, memberExpr);
// for the write-only analysis
return true;
}
// we don't care about reads from a field when inside that field parent class copy/move constructor/operator=
if (insideMoveOrCopyDecl)
void UnusedFields::checkWriteOnly(const FieldDecl* fieldDecl, const Expr* memberExpr)
{
// we don't care about reads from a field when inside the copy/move constructor/operator= for that field
if (insideMoveOrCopyDeclParent)
{
auto cxxRecordDecl1 = dyn_cast<CXXRecordDecl>(fieldDecl->getDeclContext());
auto cxxRecordDecl2 = dyn_cast<CXXRecordDecl>(insideMoveOrCopyDecl->getDeclContext());
if (cxxRecordDecl1 && cxxRecordDecl1 == cxxRecordDecl2)
return true;
RecordDecl const * cxxRecordDecl1 = fieldDecl->getParent();
if (cxxRecordDecl1 && (cxxRecordDecl1 == insideMoveOrCopyDeclParent))
return;
}
auto parentsRange = compiler.getASTContext().getParents(*memberExpr);
......@@ -268,7 +271,7 @@ bool UnusedFields::VisitMemberExpr( const MemberExpr* memberExpr )
bPotentiallyReadFrom = true;
}
if (!bPotentiallyReadFrom)
return true;
return;
break;
}
if (isa<CastExpr>(parent) || isa<MemberExpr>(parent) || isa<ParenExpr>(parent) || isa<ParenListExpr>(parent)
......@@ -404,10 +407,9 @@ bool UnusedFields::VisitMemberExpr( const MemberExpr* memberExpr )
memberExpr->dump();
}
MyFieldInfo fieldInfo = niceName(fieldDecl);
if (bPotentiallyReadFrom)
readFromSet.insert(fieldInfo);
return true;
}
bool UnusedFields::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
......@@ -425,11 +427,11 @@ bool UnusedFields::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(fieldDecl->getLocation()))) {
return true;
}
checkTouched(fieldDecl, declRefExpr);
checkTouchedFromOutside(fieldDecl, declRefExpr);
return true;
}
void UnusedFields::checkTouched(const FieldDecl* fieldDecl, const Expr* memberExpr) {
void UnusedFields::checkTouchedFromOutside(const FieldDecl* fieldDecl, const Expr* memberExpr) {
const FunctionDecl* memberExprParentFunction = parentFunctionDecl(memberExpr);
const CXXMethodDecl* methodDecl = dyn_cast_or_null<CXXMethodDecl>(memberExprParentFunction);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment