]> granicus.if.org Git - clang/commitdiff
Switch the initialization of Objective-C message parameters (as occurs
authorDouglas Gregor <dgregor@apple.com>
Wed, 21 Apr 2010 23:24:10 +0000 (23:24 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 21 Apr 2010 23:24:10 +0000 (23:24 +0000)
during message sends) over to the new initialization code and away
from the C-only CheckSingleAssignmentConstraints. The enables the use
of C++ types in method parameters and message arguments, as well as
unifying more initialiation code overall.

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

lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaInit.h
test/SemaObjCXX/message.mm
test/SemaObjCXX/objc-pointer-conv.mm

index 3af0cfc2c4832db00a129b2604a94bea4f7b82d5..e6884bac333bcebb979a63139d1a064898371c7b 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "Sema.h"
 #include "Lookup.h"
+#include "SemaInit.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprObjC.h"
@@ -204,30 +205,23 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
   bool IsError = false;
   for (unsigned i = 0; i < NumNamedArgs; i++) {
     Expr *argExpr = Args[i];
+    ParmVarDecl *Param = Method->param_begin()[i];
     assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
 
-    QualType lhsType = Method->param_begin()[i]->getType();
-    QualType rhsType = argExpr->getType();
-
-    // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
-    if (lhsType->isArrayType())
-      lhsType = Context.getArrayDecayedType(lhsType);
-    else if (lhsType->isFunctionType())
-      lhsType = Context.getPointerType(lhsType);
-
-    AssignConvertType Result =
-      CheckSingleAssignmentConstraints(lhsType, argExpr);
-    if (Result == Incompatible && !getLangOptions().CPlusPlus &&
-        CheckTransparentUnionArgumentConstraints(lhsType, argExpr)
-        == Sema::Compatible)
-      Result = Compatible;
-        
-    if (Args[i] != argExpr) // The expression was converted.
-      Args[i] = argExpr; // Make sure we store the converted expression.
+    if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
+                            Param->getType(),
+                            PDiag(diag::err_call_incomplete_argument)
+                              << argExpr->getSourceRange()))
+      return true;
 
-    IsError |=
-      DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
-                               argExpr, AA_Sending);
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+    OwningExprResult ArgE = PerformCopyInitialization(Entity,
+                                                      SourceLocation(),
+                                                      Owned(argExpr->Retain()));
+    if (ArgE.isInvalid())
+      IsError = true;
+    else
+      Args[i] = ArgE.takeAs<Expr>();
   }
 
   // Promote additional arguments to variadic methods.
index a015dd71042956b5b93dcfa5566e04ce4a5334f9..6a9efbddbdf716bbfb678af0516e0d71164c39f6 100644 (file)
@@ -3088,7 +3088,10 @@ getAssignmentAction(const InitializedEntity &Entity) {
     return Sema::AA_Initializing;
 
   case InitializedEntity::EK_Parameter:
-    // FIXME: Can we tell when we're sending vs. passing?
+    if (Entity.getDecl() && 
+        isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
+      return Sema::AA_Sending;
+
     return Sema::AA_Passing;
 
   case InitializedEntity::EK_Result:
index bfbb0f4049c28e8ccfcb5bfdcb2e352df82c6f1a..ba11470d24a3aae28aa4319396db81efa02709b4 100644 (file)
@@ -142,7 +142,12 @@ public:
   /// \brief Create the initialization entity for a parameter that is
   /// only known by its type.
   static InitializedEntity InitializeParameter(QualType Type) {
-    return InitializedEntity(EK_Parameter, SourceLocation(), Type);
+    InitializedEntity Entity;
+    Entity.Kind = EK_Parameter;
+    Entity.Type = Type;
+    Entity.Parent = 0;
+    Entity.VariableOrMember = 0;
+    return Entity;
   }
 
   /// \brief Create the initialization entity for the result of a function.
index 91b11f146cc1ff1556aee2e00b942e24feb96e8c..97ee499aff75aa8194e1a6c0532910a4ae11ada5 100644 (file)
@@ -75,3 +75,18 @@ struct identity {
   return [super method];
 }
 @end
+
+struct String {
+  String(const char *);
+};
+
+struct MutableString : public String { };
+
+// C++-specific parameter types
+@interface I5
+- method:(const String&)str1 other:(String&)str2;
+@end
+
+void test_I5(I5 *i5, String s) {
+  [i5 method:"hello" other:s];
+}
index 02ed58b0123f680f814a50bb5c2bf33f1098ccf4..2504dcedb84de0f5bcf936b3abf34373625a3c3e 100644 (file)
@@ -32,7 +32,7 @@ void RandomFunc(CFMDRef theDict, const void *key, const void *value);
 void Func (I* arg);  // expected-note {{candidate function not viable: no known conversion from 'I const *' to 'I *' for 1st argument}}
 
 void foo(const I *p, I* sel) {
-  [sel Meth : p];      // expected-error {{sending 'I const *' to parameter of incompatible type 'I *'}}
+  [sel Meth : p];      // expected-error {{cannot initialize a parameter of type 'I *' with an lvalue of type 'I const *'}}
   Func(p);             // expected-error {{no matching function for call to 'Func'}}
 }