Stop double visiting some expressions during self reference checking.

Originally, self reference checking made a double pass over some expressions
to handle reference type checking.  Now, allow HandleValue to also check
reference types, and fallback to Visit for unhandled expressions.

llvm-svn: 217203
This commit is contained in:
Richard Trieu 2014-09-04 23:19:34 +00:00
parent c4b4253f7c
commit 2a07c96737
2 changed files with 23 additions and 5 deletions

View File

@ -8207,8 +8207,6 @@ namespace {
// For conditional operators, the cast can be outside the conditional
// operator if both expressions are DeclRefExpr's.
void HandleValue(Expr *E) {
if (isReferenceType)
return;
E = E->IgnoreParens();
if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(E)) {
HandleDeclRefExpr(DRE);
@ -8223,6 +8221,7 @@ namespace {
if (BinaryConditionalOperator *BCO =
dyn_cast<BinaryConditionalOperator>(E)) {
Visit(BCO->getCond());
HandleValue(BCO->getFalseExpr());
return;
}
@ -8250,10 +8249,12 @@ namespace {
HandleDeclRefExpr(DRE);
return;
}
Visit(E);
}
// Reference types are handled here since all uses of references are
// bad, not just r-value uses.
// Reference types not handled in HandleValue are handled here since all
// uses of references are bad, not just r-value uses.
void VisitDeclRefExpr(DeclRefExpr *E) {
if (isReferenceType)
HandleDeclRefExpr(E);
@ -8261,8 +8262,10 @@ namespace {
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue ||
(isRecordType && E->getCastKind() == CK_NoOp))
(isRecordType && E->getCastKind() == CK_NoOp)) {
HandleValue(E->getSubExpr());
return;
}
Inherited::VisitImplicitCastExpr(E);
}
@ -8329,6 +8332,7 @@ namespace {
if (FunctionDecl *FD = E->getDirectCallee()) {
if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) {
HandleValue(E->getArg(0));
return;
}
}
}
@ -8336,6 +8340,14 @@ namespace {
Inherited::VisitCallExpr(E);
}
// A custom visitor for BinaryConditionalOperator is needed because the
// regular visitor would check the condition and true expression separately
// but both point to the same place giving duplicate diagnostics.
void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
Visit(E->getCond());
Visit(E->getFalseExpr());
}
void HandleDeclRefExpr(DeclRefExpr *DRE) {
Decl* ReferenceDecl = DRE->getDecl();
if (OrigDecl != ReferenceDecl) return;

View File

@ -566,6 +566,12 @@ namespace references {
int &e = d ?: e; // expected-warning{{reference 'e' is not yet bound to a value when used within its own initialization}}
int &f = f ?: d; // expected-warning{{reference 'f' is not yet bound to a value when used within its own initialization}}
int &return_ref1(int);
int &return_ref2(int&);
int &g = return_ref1(g); // expected-warning{{reference 'g' is not yet bound to a value when used within its own initialization}}
int &h = return_ref2(h); // expected-warning{{reference 'h' is not yet bound to a value when used within its own initialization}}
struct S {
S() : a(a) {} // expected-warning{{reference 'a' is not yet bound to a value when used here}}
int &a;