aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2012-10-03 00:41:36 +0000
committerRichard Trieu <rtrieu@google.com>2012-10-03 00:41:36 +0000
commit6b2cc42f1504db6577fd67fa55ef023254744e2c (patch)
treefd66b4abce91aee016adb01510841d4c3eacebf6 /lib/Sema/SemaDecl.cpp
parent3d3f1f7c79c33a2e280dd289056ce68c95aa4cce (diff)
Change how the SelfReferenceChecker handles MemberExpr. Instead of treating
each one separately, process a stack of MemberExpr's as a single unit so that static calls and member access will not be warned on. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165074 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp50
1 files changed, 39 insertions, 11 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ddb41edc64..5a33230b2c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6276,6 +6276,20 @@ namespace {
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
HandleValue(CO->getTrueExpr());
HandleValue(CO->getFalseExpr());
+ return;
+ }
+
+ if (isa<MemberExpr>(E)) {
+ Expr *Base = E->IgnoreParenImpCasts();
+ while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
+ // Check for static member variables and don't warn on them.
+ if (!isa<FieldDecl>(ME->getMemberDecl()))
+ return;
+ Base = ME->getBase()->IgnoreParenImpCasts();
+ }
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base))
+ HandleDeclRefExpr(DRE);
+ return;
}
}
@@ -6287,7 +6301,7 @@ namespace {
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
- if ((!isRecordType && E->getCastKind() == CK_LValueToRValue) ||
+ if (E->getCastKind() == CK_LValueToRValue ||
(isRecordType && E->getCastKind() == CK_NoOp))
HandleValue(E->getSubExpr());
@@ -6298,22 +6312,36 @@ namespace {
// Don't warn on arrays since they can be treated as pointers.
if (E->getType()->canDecayToPointerType()) return;
- ValueDecl *VD = E->getMemberDecl();
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(VD);
- if (isa<FieldDecl>(VD) || (MD && !MD->isStatic()))
- if (DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) {
+ // Warn when a non-static method call is followed by non-static member
+ // field accesses, which is followed by a DeclRefExpr.
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl());
+ bool Warn = (MD && !MD->isStatic());
+ Expr *Base = E->getBase()->IgnoreParenImpCasts();
+ while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
+ if (!isa<FieldDecl>(ME->getMemberDecl()))
+ Warn = false;
+ Base = ME->getBase()->IgnoreParenImpCasts();
+ }
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (Warn)
HandleDeclRefExpr(DRE);
- return;
- }
+ return;
+ }
- Inherited::VisitMemberExpr(E);
+ // The base of a MemberExpr is not a MemberExpr or a DeclRefExpr.
+ // Visit that expression.
+ Visit(Base);
}
void VisitUnaryOperator(UnaryOperator *E) {
// For POD record types, addresses of its own members are well-defined.
- if (E->getOpcode() == UO_AddrOf && isRecordType && isPODType &&
- isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) return;
+ if (E->getOpcode() == UO_AddrOf && isRecordType &&
+ isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) {
+ if (!isPODType)
+ HandleValue(E->getSubExpr());
+ return;
+ }
Inherited::VisitUnaryOperator(E);
}