[cfe-commits] r167896 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseTentative.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjCXX/unknown-anytype.mm

John McCall rjmccall at apple.com
Tue Nov 13 16:49:39 PST 2012


Author: rjmccall
Date: Tue Nov 13 18:49:39 2012
New Revision: 167896

URL: http://llvm.org/viewvc/llvm-project?rev=167896&view=rev
Log:
Accept and pass arguments to __unknown_anytype in argument
positions of Objective-C methods.

It is possible to recover a lot of type information about
Objective-C methods from the reflective metadata for their
implementations.  This information is not rich when it
comes to struct types, however, and it is not possible to
produce a type in the debugger's round-tripped AST which
will really do anything useful during type-checking.
Therefore we allow __unknown_anytype in these positions,
which essentially disables type-checking for that argument.
We infer the parameter type to be the unqualified type of
the argument expression unless that expression is an
explicit cast, in which case it becomes the type-as-written
of that cast.

rdar://problem/12565338

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjCXX/unknown-anytype.mm

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=167896&r1=167895&r2=167896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Nov 13 18:49:39 2012
@@ -6812,6 +6812,13 @@
   /// given type.
   ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
 
+  /// \brief Handle an expression that's being passed to an
+  /// __unknown_anytype parameter.
+  ///
+  /// \return the effective parameter type to use, or null if the
+  ///   argument is invalid.
+  QualType checkUnknownAnyArg(Expr *&result);
+
   // CheckVectorCast - check type constraints for vectors.
   // Since vectors are an extension, there are no C standard reference for this.
   // We allow casting between vectors and integer datatypes of the same size.

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=167896&r1=167895&r2=167896&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Nov 13 18:49:39 2012
@@ -3652,6 +3652,9 @@
   case tok::kw_volatile:
   case tok::kw_restrict:
 
+    // Debugger support.
+  case tok::kw___unknown_anytype:
+
     // typedef-name
   case tok::annot_typename:
     return true;
@@ -3751,6 +3754,9 @@
     // Modules
   case tok::kw___module_private__:
 
+    // Debugger support
+  case tok::kw___unknown_anytype:
+
     // type-specifiers
   case tok::kw_short:
   case tok::kw_long:

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=167896&r1=167895&r2=167896&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Tue Nov 13 18:49:39 2012
@@ -837,6 +837,7 @@
   case tok::kw___vector:
   case tok::kw___pixel:
   case tok::kw__Atomic:
+  case tok::kw___unknown_anytype:
     return TPResult::False();
 
   default:
@@ -1056,6 +1057,9 @@
 
     // Modules
   case tok::kw___module_private__:
+
+    // Debugger support
+  case tok::kw___unknown_anytype:
       
     // type-specifier:
     //   simple-type-specifier

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=167896&r1=167895&r2=167896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Nov 13 18:49:39 2012
@@ -11850,6 +11850,22 @@
   return RebuildUnknownAnyExpr(*this, ToType).Visit(E);
 }
 
+QualType Sema::checkUnknownAnyArg(Expr *&arg) {
+  // Filter out placeholders.
+  ExprResult argR = CheckPlaceholderExpr(arg);
+  if (argR.isInvalid()) return QualType();
+  arg = argR.take();
+
+  // If the argument is an explicit cast, use that exact type as the
+  // effective parameter type.
+  if (ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg)) {
+    return castArg->getTypeAsWritten();
+  }
+
+  // Otherwise, try to pass by value.
+  return arg->getType().getUnqualifiedType();
+}
+
 static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
   Expr *orig = E;
   unsigned diagID = diag::err_uncasted_use_of_unknown_any;

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=167896&r1=167895&r2=167896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Nov 13 18:49:39 2012
@@ -1196,6 +1196,19 @@
         !param->hasAttr<CFConsumedAttr>())
       argExpr = stripARCUnbridgedCast(argExpr);
 
+    // If the parameter is __unknown_anytype, infer its type
+    // from the argument.
+    if (param->getType() == Context.UnknownAnyTy) {
+      QualType paramType = checkUnknownAnyArg(argExpr);
+      if (paramType.isNull()) {
+        IsError = true;
+        continue;
+      }
+
+      // Update the parameter type in-place.
+      param->setType(paramType);
+    }
+
     if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
                             param->getType(),
                             diag::err_call_incomplete_argument, argExpr))

Modified: cfe/trunk/test/SemaObjCXX/unknown-anytype.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/unknown-anytype.mm?rev=167896&r1=167895&r2=167896&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/unknown-anytype.mm (original)
+++ cfe/trunk/test/SemaObjCXX/unknown-anytype.mm Tue Nov 13 18:49:39 2012
@@ -7,3 +7,48 @@
     [x foo]; // expected-error {{no known method '-foo'; cast the message send to the method's return type}}
   }
 }
+
+// rdar://problem/12565338
+ at interface Test1
+- (void) test_a: (__unknown_anytype)foo;
+- (void) test_b: (__unknown_anytype)foo;
+- (void) test_c: (__unknown_anytype)foo;
+ at end
+namespace test1 {
+  struct POD {
+    int x;
+  };
+
+  void a(Test1 *obj) {
+    POD v;
+    [obj test_a: v];
+  }
+
+  struct Uncopyable {
+    Uncopyable();
+  private:
+    Uncopyable(const Uncopyable &); // expected-note {{declared private here}}
+  };
+
+  void b(Test1 *obj) {
+    Uncopyable v;
+    [obj test_b: v]; // expected-error {{calling a private constructor}}
+  }
+
+  void c(Test1 *obj) {
+    Uncopyable v;
+    [obj test_c: (const Uncopyable&) v];
+  }
+}
+
+// Just test that we can declare a function taking __unknown_anytype.
+// For now, we don't actually need to make calling something like this
+// work; if that changes, here's what's required:
+//   - get this call through overload resolution somehow,
+//   - update the function-call argument-passing code like the
+//     message-send code, and
+//   - rewrite the function expression to have a type that doesn't
+//     involving __unknown_anytype.
+namespace test2 {
+  void foo(__unknown_anytype x);
+}





More information about the cfe-commits mailing list