[analyzer] Member function calls that use qualified names are non-virtual.

C++11 [expr.call]p1: ...If the selected function is non-virtual, or if the
  id-expression in the class member access expression is a qualified-id,
  that function is called. Otherwise, its final overrider in the dynamic type
  of the object expression is called.

<rdar://problem/12255556>

llvm-svn: 163577
This commit is contained in:
Jordan Rose 2012-09-11 00:31:02 +00:00
parent a39ad077c9
commit 12f669e3cd
4 changed files with 49 additions and 0 deletions

View File

@ -549,6 +549,8 @@ public:
}
virtual const Expr *getCXXThisExpr() const;
virtual RuntimeDefinition getRuntimeDefinition() const;
virtual Kind getKind() const { return CE_CXXMember; }

View File

@ -496,6 +496,18 @@ const Expr *CXXMemberCall::getCXXThisExpr() const {
return getOriginExpr()->getImplicitObjectArgument();
}
RuntimeDefinition CXXMemberCall::getRuntimeDefinition() const {
// C++11 [expr.call]p1: ...If the selected function is non-virtual, or if the
// id-expression in the class member access expression is a qualified-id,
// that function is called. Otherwise, its final overrider in the dynamic type
// of the object expression is called.
if (const MemberExpr *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee()))
if (ME->hasQualifier())
return AnyFunctionCall::getRuntimeDefinition();
return CXXInstanceCall::getRuntimeDefinition();
}
const Expr *CXXMemberOperatorCall::getCXXThisExpr() const {
return getOriginExpr()->getArg(0);

View File

@ -281,3 +281,23 @@ namespace MultipleInheritanceVirtualDtors {
SubclassB b;
}
}
namespace ExplicitDestructorCall {
class VirtualDtor {
public:
virtual ~VirtualDtor() {
clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
}
};
class Subclass : public VirtualDtor {
public:
virtual ~Subclass() {
clang_analyzer_checkInlined(false); // no-warning
}
};
void destroy(Subclass *obj) {
obj->VirtualDtor::~VirtualDtor();
}
}

View File

@ -325,3 +325,18 @@ namespace VirtualWithSisterCasts {
clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
}
}
namespace QualifiedCalls {
void test(One *object) {
// This uses the One class from the top of the file.
clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}
clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}
// getZero is non-virtual.
clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
}
}