]> granicus.if.org Git - clang/commitdiff
Stop double visiting some expressions during self reference checking.
authorRichard Trieu <rtrieu@google.com>
Thu, 4 Sep 2014 23:19:34 +0000 (23:19 +0000)
committerRichard Trieu <rtrieu@google.com>
Thu, 4 Sep 2014 23:19:34 +0000 (23:19 +0000)
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

lib/Sema/SemaDecl.cpp
test/SemaCXX/uninitialized.cpp

index f5ba0ea90327585b0dca7ed37ee54764af75cff2..8834705e74294f4eb4c00984e62449c5c20543ff 100644 (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;
index b0b4ef672dbd28c8b5a1b0964f9f121dca0b90eb..8d0338c3d83c637fd658db0d94da46e6beaf433f 100644 (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;