]> granicus.if.org Git - clang/commitdiff
When checking for illegal expressions in a default-argument
authorJohn McCall <rjmccall@apple.com>
Tue, 9 Apr 2013 01:56:28 +0000 (01:56 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 9 Apr 2013 01:56:28 +0000 (01:56 +0000)
expression, look through pseudo-object expressions.

rdar://13602832

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179080 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaObjCXX/property-reference.mm

index 8f8e22a68a277905bec3702eb8cbdf7559574051..ddc077456b23d34693f642467355b6638684a3a7 100644 (file)
@@ -65,6 +65,7 @@ namespace {
     bool VisitDeclRefExpr(DeclRefExpr *DRE);
     bool VisitCXXThisExpr(CXXThisExpr *ThisE);
     bool VisitLambdaExpr(LambdaExpr *Lambda);
+    bool VisitPseudoObjectExpr(PseudoObjectExpr *POE);
   };
 
   /// VisitExpr - Visit all of the children of this expression.
@@ -115,6 +116,23 @@ namespace {
                << ThisE->getSourceRange();
   }
 
+  bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
+    bool Invalid = false;
+    for (PseudoObjectExpr::semantics_iterator
+           i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) {
+      Expr *E = *i;
+
+      // Look through bindings.
+      if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
+        E = OVE->getSourceExpr();
+        assert(E && "pseudo-object binding without source expression?");
+      }
+
+      Invalid |= Visit(E);
+    }
+    return Invalid;
+  }
+
   bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) {
     // C++11 [expr.lambda.prim]p13:
     //   A lambda-expression appearing in a default argument shall not
index b86ae5e9f51ddc3a3974b440f8efe30562563434..cfac9f30dbd4c76ecf2f4b07f9f731ab5288168d 100644 (file)
@@ -57,3 +57,21 @@ template<typename T> void f() {
 }
 
 template void f<int>();
+
+// rdar://13602832
+//
+// Make sure that the default-argument checker looks through
+// pseudo-object expressions correctly.  The default argument
+// needs to force l2r to test this effectively because the checker
+// is syntactic and runs before placeholders are handled.
+@interface Test13602832
+- (int) x;
+@end
+namespace test13602832 {
+  template <int N> void foo(Test13602832 *a, int limit = a.x + N) {} // expected-error {{default argument references parameter 'a'}}
+
+  void test(Test13602832 *a) {
+    // FIXME: this is a useless cascade error.
+    foo<1024>(a); // expected-error {{no matching function}}
+  }
+}