[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:
parent
a39ad077c9
commit
12f669e3cd
|
@ -549,6 +549,8 @@ public:
|
|||
}
|
||||
|
||||
virtual const Expr *getCXXThisExpr() const;
|
||||
|
||||
virtual RuntimeDefinition getRuntimeDefinition() const;
|
||||
|
||||
virtual Kind getKind() const { return CE_CXXMember; }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue