From: Richard Trieu Date: Thu, 4 Sep 2014 23:19:34 +0000 (+0000) Subject: Stop double visiting some expressions during self reference checking. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b6150769d848012811c89002f71892f07a3cb43;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217203 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f5ba0ea903..8834705e74 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(E)) { HandleDeclRefExpr(DRE); @@ -8223,6 +8221,7 @@ namespace { if (BinaryConditionalOperator *BCO = dyn_cast(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; diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index b0b4ef672d..8d0338c3d8 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -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;