[cfe-commits] r129269 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/OperationKinds.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Expr.cpp lib/AST/ExprConstant.cpp lib/CodeGen/CGCXXABI.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/ItaniumCXXABI.cpp lib/Sema/SemaExpr.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/CodeGenCXX/unknown-anytype.cpp test/SemaCXX/unknown-anytype.cpp

John McCall rjmccall at apple.com
Mon Apr 11 00:02:51 PDT 2011


Author: rjmccall
Date: Mon Apr 11 02:02:50 2011
New Revision: 129269

URL: http://llvm.org/viewvc/llvm-project?rev=129269&view=rev
Log:
More __unknown_anytype work.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/OperationKinds.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp
    cfe/trunk/test/SemaCXX/unknown-anytype.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Apr 11 02:02:50 2011
@@ -2222,6 +2222,7 @@
     case CK_FloatingComplexToBoolean:
     case CK_IntegralComplexToBoolean:
     case CK_ResolveUnknownAnyType:
+    case CK_ResolveUnknownAnyTypeToReference:
     case CK_LValueBitCast:            // -> bool&
     case CK_UserDefinedConversion:    // operator bool()
       assert(path_empty() && "Cast kind should not have a base path!");

Modified: cfe/trunk/include/clang/AST/OperationKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OperationKinds.h?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OperationKinds.h (original)
+++ cfe/trunk/include/clang/AST/OperationKinds.h Mon Apr 11 02:02:50 2011
@@ -248,7 +248,10 @@
   CK_IntegralComplexToFloatingComplex,
 
   /// \brief Assign an unknown-any declaration a type.
-  CK_ResolveUnknownAnyType
+  CK_ResolveUnknownAnyType,
+
+  /// \brief Assign an unknown-any declaration a reference type.
+  CK_ResolveUnknownAnyTypeToReference
 };
 
 #define CK_Invalid ((CastKind) -1)

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 11 02:02:50 2011
@@ -3851,8 +3851,14 @@
   "%0 does not refer to the name of a parameter pack; did you mean %1?">;
 def note_parameter_pack_here : Note<"parameter pack %0 declared here">;
 
-def err_bad_use_of_unknown_any : Error<
-  "no known type for %0; must explicitly cast this expression to use it">;
+def err_uncasted_use_of_unknown_any : Error<
+  "%0 has unknown type;  cast it to its declared type to use it">;
+def err_uncasted_call_of_unknown_any : Error<
+  "%0 has unknown return type;  cast the call to its declared return type">;
+def err_unsupported_unknown_any_decl : Error<
+  "%0 has unknown type, which is unsupported for this kind of declaration">;
+def err_unsupported_unknown_any_expr : Error<
+  "unsupported expression with unknown type">;
 
 } // end of sema category
 

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Apr 11 02:02:50 2011
@@ -1057,6 +1057,8 @@
     return "IntegralComplexToFloatingComplex";
   case CK_ResolveUnknownAnyType:
     return "ResolveUnknownAnyType";
+  case CK_ResolveUnknownAnyTypeToReference:
+    return "ResolveUnknownAnyTypeToReference";
   }
 
   llvm_unreachable("Unhandled cast kind!");

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Apr 11 02:02:50 2011
@@ -1799,6 +1799,7 @@
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
   case CK_ResolveUnknownAnyType:
+  case CK_ResolveUnknownAnyTypeToReference:
     return false;
 
   case CK_LValueToRValue:
@@ -2353,6 +2354,7 @@
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
   case CK_ResolveUnknownAnyType:
+  case CK_ResolveUnknownAnyTypeToReference:
     return false;
 
   case CK_FloatingRealToComplex: {

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Mon Apr 11 02:02:50 2011
@@ -99,7 +99,8 @@
   return GetBogusMemberPointer(CGM, QualType(MPT, 0));
 }
 
-llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
+                                            QualType unknownType) {
   return GetBogusMemberPointer(CGM,
                          CGM.getContext().getMemberPointerType(MD->getType(),
                                          MD->getParent()->getTypeForDecl()));

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Mon Apr 11 02:02:50 2011
@@ -119,7 +119,12 @@
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
   /// Create a member pointer for the given method.
-  virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+  ///
+  /// \param unknownType - if non-null, use this type as the operand
+  ///   to CodeGenModule::getAddrOfUnknownAnyDecl instead of
+  ///   fetching the method's address in the normal way
+  virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
+                                            QualType unknownType = QualType());
 
   /// Create a member pointer for the given field.
   virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Apr 11 02:02:50 2011
@@ -1792,6 +1792,35 @@
   return MakeAddrLValue(phi, expr->getType());
 }
 
+static LValue emitUnknownAnyLValue(CodeGenFunction &CGF,
+                                   const Expr *operand,
+                                   QualType resolvedType) {
+  const ValueDecl *decl;
+  if (const DeclRefExpr *ref = dyn_cast<DeclRefExpr>(operand)) {
+    decl = ref->getDecl();
+  } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(operand)) {
+    decl = mem->getMemberDecl();
+
+    // Emit (and ignore) the base.
+    if (mem->isArrow())
+      CGF.EmitScalarExpr(mem->getBase());
+    else
+      CGF.EmitLValue(mem->getBase());
+  } else {
+    llvm_unreachable("unexpected operand of unknown-any resolution!");
+    decl = 0;
+  }
+  llvm::Value *addr = CGF.CGM.getAddrOfUnknownAnyDecl(decl, resolvedType);
+
+  QualType type = resolvedType;
+  if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
+    addr = CGF.Builder.CreateLoad(addr, "ref.value");
+    type = ref->getPointeeType();
+  }
+
+  return CGF.MakeAddrLValue(addr, type);
+}
+
 /// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
 /// If the cast is a dynamic_cast, we can have the usual lvalue result,
 /// otherwise if a cast is needed by the code generator in an lvalue context,
@@ -1930,11 +1959,12 @@
                                            ConvertType(ToType));
     return MakeAddrLValue(V, E->getType());
   }
-  case CK_ResolveUnknownAnyType: {
-    const DeclRefExpr *declRef = cast<DeclRefExpr>(E->getSubExpr());
-    llvm::Constant *addr = CGM.getAddrOfUnknownAnyDecl(declRef->getDecl(),
-                                                       E->getType());
-    return MakeAddrLValue(addr, E->getType());
+  case CK_ResolveUnknownAnyType:
+    return emitUnknownAnyLValue(*this, E->getSubExpr(), E->getType());
+  case CK_ResolveUnknownAnyTypeToReference: {
+    // l-value vs. r-value reference type shouldn't matter here.
+    QualType type = getContext().getLValueReferenceType(E->getType());
+    return emitUnknownAnyLValue(*this, E->getSubExpr(), type);
   }
   }
   

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Mon Apr 11 02:02:50 2011
@@ -311,6 +311,7 @@
     break;
 
   case CK_ResolveUnknownAnyType:
+  case CK_ResolveUnknownAnyTypeToReference:
     EmitAggLoadOfLValue(E);
     break;
       

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Mon Apr 11 02:02:50 2011
@@ -167,10 +167,12 @@
 // extensions allowing explicit constructor function call.
 RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
                                               ReturnValueSlot ReturnValue) {
-  if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens())) 
+  const Expr *callee = CE->getCallee()->IgnoreParens();
+
+  if (isa<BinaryOperator>(callee))
     return EmitCXXMemberPointerCallExpr(CE, ReturnValue);
-      
-  const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens());
+
+  const MemberExpr *ME = cast<MemberExpr>(callee);
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
 
   CGDebugInfo *DI = getDebugInfo();

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Apr 11 02:02:50 2011
@@ -553,6 +553,7 @@
     case CK_ToVoid:
     case CK_Dynamic:
     case CK_ResolveUnknownAnyType:
+    case CK_ResolveUnknownAnyTypeToReference:
       return 0;
 
     // These might need to be supported for constexpr.

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Apr 11 02:02:50 2011
@@ -1128,6 +1128,19 @@
   }
 
   case CK_ResolveUnknownAnyType:
+    // Special case: resolving a member pointer constant.
+    if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(E)) {
+      DeclRefExpr *declRef = cast<DeclRefExpr>(uo->getSubExpr());
+      const CXXMethodDecl *method = cast<CXXMethodDecl>(declRef->getDecl());
+
+      const MemberPointerType *mpt = CE->getType()->castAs<MemberPointerType>();
+      QualType resolvedType = mpt->getPointeeType();
+
+      return CGF.CGM.getCXXABI().EmitMemberPointer(method, resolvedType);
+    }
+    // fallthrough
+
+  case CK_ResolveUnknownAnyTypeToReference:
     return EmitLoadOfLValue(CE);
       
   case CK_LValueToRValue:

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Apr 11 02:02:50 2011
@@ -78,7 +78,8 @@
 
   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
-  llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+  llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
+                                    QualType unknownType);
   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
                                         CharUnits offset);
 
@@ -502,7 +503,8 @@
   return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
 }
 
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
+                                                 QualType unknownType) {
   assert(MD->isInstance() && "Member function must not be static!");
   MD = MD->getCanonicalDecl();
 
@@ -537,20 +539,27 @@
       MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
     }
   } else {
-    const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-    const llvm::Type *Ty;
-    // Check whether the function has a computable LLVM signature.
-    if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
-      // The function has a computable LLVM signature; use the correct type.
-      Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
+    llvm::Constant *addr;
+    if (!unknownType.isNull()) {
+      addr = CGM.getAddrOfUnknownAnyDecl(MD, unknownType);
     } else {
-      // Use an arbitrary non-function type to tell GetAddrOfFunction that the
-      // function type is incomplete.
-      Ty = ptrdiff_t;
+      QualType fnType = MD->getType();
+      const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
+      const llvm::Type *Ty;
+      // Check whether the function has a computable LLVM signature.
+      if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+        // The function has a computable LLVM signature; use the correct type.
+        Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
+                                   FPT->isVariadic());
+      } else {
+        // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+        // function type is incomplete.
+        Ty = ptrdiff_t;
+      }
+      addr = CGM.GetAddrOfFunction(MD, Ty);
     }
 
-    llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
-    MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
+    MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t);
     MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
   }
   

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr 11 02:02:50 2011
@@ -4734,10 +4734,24 @@
     if (result.isInvalid()) return ExprError();
     args[i] = result.take();
 
-    // Do l2r conversions on all the arguments.
-    S.DefaultLvalueConversion(args[i]);
+    QualType argType;
 
-    argTypes.push_back(args[i]->getType());
+    // If the argument is an explicit cast (possibly parenthesized),
+    // use that type exactly.  This allows users to pass by reference.
+    if (ExplicitCastExpr *castExpr
+          = dyn_cast<ExplicitCastExpr>(args[i]->IgnoreParens())) {
+      argType = castExpr->getTypeAsWritten();
+
+    // Otherwise, do an l2r conversion on the argument before grabbing
+    // its type.
+    } else {
+      ExprResult result = S.DefaultLvalueConversion(args[i]);
+      if (result.isInvalid()) return ExprError();
+      args[i] = result.take();
+      argType = args[i]->getType();
+    }
+
+    argTypes.push_back(argType);
   }
 
   // Resolve the symbol to a function type that returns an unknown-any
@@ -10145,6 +10159,10 @@
 }
 
 namespace {
+  /// A visitor for rebuilding an expression of type __unknown_anytype
+  /// into one which resolves the type directly on the referring
+  /// expression.  Strict preservation of the original source
+  /// structure is not a goal.
   struct RebuildUnknownAnyExpr
     : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
 
@@ -10157,64 +10175,19 @@
       : S(S), DestType(castType) {}
 
     ExprResult VisitStmt(Stmt *S) {
-      llvm_unreachable("unexpected expression kind!");
+      llvm_unreachable("unexpected statement!");
       return ExprError();
     }
 
-    ExprResult VisitCallExpr(CallExpr *call) {
-      Expr *callee = call->getCallee();
-
-      bool wasBlock;
-      QualType type = callee->getType();
-      if (const PointerType *ptr = type->getAs<PointerType>()) {
-        type = ptr->getPointeeType();
-        wasBlock = false;
-      } else {
-        type = type->castAs<BlockPointerType>()->getPointeeType();
-        wasBlock = true;
-      }
-      const FunctionType *fnType = type->castAs<FunctionType>();
-
-      // Verify that this is a legal result type of a function.
-      if (DestType->isArrayType() || DestType->isFunctionType()) {
-        unsigned diagID = diag::err_func_returning_array_function;
-        if (wasBlock) diagID = diag::err_block_returning_array_function;
-
-        S.Diag(call->getExprLoc(), diagID)
-          << DestType->isFunctionType() << DestType;
-        return ExprError();
-      }
-
-      // Otherwise, go ahead and set DestType as the call's result.
-      call->setType(DestType.getNonLValueExprType(S.Context));
-      call->setValueKind(Expr::getValueKindForType(DestType));
-      assert(call->getObjectKind() == OK_Ordinary);
-
-      // Rebuild the function type, replacing the result type with DestType.
-      if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType))
-        DestType = S.Context.getFunctionType(DestType,
-                                             proto->arg_type_begin(),
-                                             proto->getNumArgs(),
-                                             proto->getExtProtoInfo());
-      else
-        DestType = S.Context.getFunctionNoProtoType(DestType,
-                                                    fnType->getExtInfo());
-
-      // Rebuild the appropriate pointer-to-function type.
-      if (wasBlock)
-        DestType = S.Context.getBlockPointerType(DestType);
-      else
-        DestType = S.Context.getPointerType(DestType);
-
-      // Finally, we can recurse.
-      ExprResult calleeResult = Visit(callee);
-      if (!calleeResult.isUsable()) return ExprError();
-      call->setCallee(calleeResult.take());
-
-      // Bind a temporary if necessary.
-      return S.MaybeBindToTemporary(call);
+    ExprResult VisitExpr(Expr *expr) {
+      S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+        << expr->getSourceRange();
+      return ExprError();
     }
 
+    ExprResult VisitCallExpr(CallExpr *call);
+    ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message);
+
     /// Rebuild an expression which simply semantically wraps another
     /// expression which it shares the type and value kind of.
     template <class T> ExprResult rebuildSugarExpr(T *expr) {
@@ -10236,45 +10209,243 @@
       return rebuildSugarExpr(op);
     }
 
-    ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice) {
-      // Rebuild an inner resolution by stripping it and propagating
-      // the new type down.
-      if (ice->getCastKind() == CK_ResolveUnknownAnyType)
-        return Visit(ice->getSubExpr());
-
-      // The only other case we should be able to get here is a
-      // function-to-pointer decay.
-      assert(ice->getCastKind() == CK_FunctionToPointerDecay);
-      ice->setType(DestType);
-      assert(ice->getValueKind() == VK_RValue);
-      assert(ice->getObjectKind() == OK_Ordinary);
+    ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice);
 
-      // Rebuild the sub-expression as the pointee (function) type.
-      DestType = DestType->castAs<PointerType>()->getPointeeType();
+    ExprResult resolveDecl(Expr *expr, NamedDecl *decl);
 
-      ExprResult result = Visit(ice->getSubExpr());
-      if (!result.isUsable()) return ExprError();
+    ExprResult VisitMemberExpr(MemberExpr *mem);
 
-      ice->setSubExpr(result.take());
-      return S.Owned(ice);
+    ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
+      return resolveDecl(ref, ref->getDecl());
     }
+  };
+}
 
-    ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
-      ExprValueKind valueKind = VK_LValue;
-      if (S.getLangOptions().CPlusPlus) {
-        // FIXME: if the value was resolved as a reference type, we
-        // should really remember that somehow, or else we'll be
-        // missing a load.
-        DestType = DestType.getNonReferenceType();
-      } else if (DestType->isFunctionType()) {
-        valueKind = VK_RValue;
-      }
+/// Rebuilds a call expression which yielded __unknown_anytype.
+ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) {
+  Expr *callee = call->getCallee();
+
+  enum FnKind {
+    FK_Function,
+    FK_FunctionPointer,
+    FK_BlockPointer
+  };
+
+  FnKind kind;
+  QualType type = callee->getType();
+  if (type->isFunctionType()) {
+    assert(isa<CXXMemberCallExpr>(call) || isa<CXXOperatorCallExpr>(call));
+    kind = FK_Function;
+  } else if (const PointerType *ptr = type->getAs<PointerType>()) {
+    type = ptr->getPointeeType();
+    kind = FK_FunctionPointer;
+  } else {
+    type = type->castAs<BlockPointerType>()->getPointeeType();
+    kind = FK_BlockPointer;
+  }
+  const FunctionType *fnType = type->castAs<FunctionType>();
+
+  // Verify that this is a legal result type of a function.
+  if (DestType->isArrayType() || DestType->isFunctionType()) {
+    unsigned diagID = diag::err_func_returning_array_function;
+    if (kind == FK_BlockPointer)
+      diagID = diag::err_block_returning_array_function;
 
-      return S.Owned(ImplicitCastExpr::Create(S.Context, DestType,
-                                              CK_ResolveUnknownAnyType,
-                                              ref, 0, valueKind));
+    S.Diag(call->getExprLoc(), diagID)
+      << DestType->isFunctionType() << DestType;
+    return ExprError();
+  }
+
+  // Otherwise, go ahead and set DestType as the call's result.
+  call->setType(DestType.getNonLValueExprType(S.Context));
+  call->setValueKind(Expr::getValueKindForType(DestType));
+  assert(call->getObjectKind() == OK_Ordinary);
+
+  // Rebuild the function type, replacing the result type with DestType.
+  if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType))
+    DestType = S.Context.getFunctionType(DestType,
+                                         proto->arg_type_begin(),
+                                         proto->getNumArgs(),
+                                         proto->getExtProtoInfo());
+  else
+    DestType = S.Context.getFunctionNoProtoType(DestType,
+                                                fnType->getExtInfo());
+
+  // Rebuild the appropriate pointer-to-function type.
+  switch (kind) {
+  case FK_Function:
+    // Nothing to do.
+    break;
+
+  case FK_FunctionPointer:
+    DestType = S.Context.getPointerType(DestType);
+    break;
+
+  case FK_BlockPointer:
+    DestType = S.Context.getBlockPointerType(DestType);
+    break;
+  }
+
+  // Finally, we can recurse.
+  ExprResult calleeResult = Visit(callee);
+  if (!calleeResult.isUsable()) return ExprError();
+  call->setCallee(calleeResult.take());
+
+  // Bind a temporary if necessary.
+  return S.MaybeBindToTemporary(call);
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) {
+  // This is a long series of hacks around the problem that:
+  //  - we can't just cast the method because it's not an expr,
+  //  - we don't want to modify it in place, and
+  //  - there's no way to override the declared result type
+  //    of a method on a per-call basis.
+
+  const ReferenceType *refTy = DestType->getAs<ReferenceType>();
+  if (refTy) {
+    // Hack 1: if we're returning a reference, make the message
+    // send return a pointer instead.
+    DestType = S.Context.getPointerType(refTy->getPointeeType());
+  }
+
+  // Change the type of the message.
+  msg->setType(DestType);
+  assert(msg->getValueKind() == VK_RValue);
+
+  // Hack 2: remove the method decl so that clients won't just
+  // ignore the expression's type.  This is imperfect and can lead
+  // to expressions being completely lost.
+  msg->setSelector(msg->getMethodDecl()->getSelector());
+
+  // Hack 3: if we're returning a reference, dereference the
+  // pointer return.
+  Expr *result = msg;
+  if (refTy) {
+    SourceLocation loc;
+    result = new (S.Context) UnaryOperator(result, UO_Deref,
+                                           refTy->getPointeeType(),
+                                           VK_LValue, OK_Ordinary, loc);
+
+    // Hack 4: if we're returning an *rvalue* reference, cast to that.
+    if (isa<RValueReferenceType>(refTy)) {
+      TypeSourceInfo *tsi =
+        S.Context.getTrivialTypeSourceInfo(QualType(refTy, 0), loc);
+      result = CStyleCastExpr::Create(S.Context, refTy->getPointeeType(),
+                                      VK_XValue, CK_LValueBitCast,
+                                      result, 0, tsi, loc, loc);
     }
-  };
+  }
+
+  return S.MaybeBindToTemporary(result);
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) {
+  // Rebuild an inner resolution by stripping it and propagating
+  // the new type down.
+  if (ice->getCastKind() == CK_ResolveUnknownAnyType)
+    return Visit(ice->getSubExpr());
+
+  // The only other case we should be able to get here is a
+  // function-to-pointer decay.
+  assert(ice->getCastKind() == CK_FunctionToPointerDecay);
+  ice->setType(DestType);
+  assert(ice->getValueKind() == VK_RValue);
+  assert(ice->getObjectKind() == OK_Ordinary);
+
+  // Rebuild the sub-expression as the pointee (function) type.
+  DestType = DestType->castAs<PointerType>()->getPointeeType();
+
+  ExprResult result = Visit(ice->getSubExpr());
+  if (!result.isUsable()) return ExprError();
+
+  ice->setSubExpr(result.take());
+  return S.Owned(ice);
+}
+
+ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *decl) {
+  ExprValueKind valueKind = VK_LValue;
+  CastKind castKind = CK_ResolveUnknownAnyType;
+  QualType type = DestType;
+
+  // We know how to make this work for certain kinds of decls:
+
+  //  - functions
+  if (isa<FunctionDecl>(decl)) {
+    if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
+      if (method->isInstance()) valueKind = VK_RValue;
+
+    // This is true because FunctionDecls must always have function
+    // type, so we can't be resolving the entire thing at once.
+    assert(type->isFunctionType());
+
+    // Function references aren't l-values in C.
+    if (!S.getLangOptions().CPlusPlus)
+      valueKind = VK_RValue;
+
+  //  - variables
+  } else if (isa<VarDecl>(decl)) {
+    if (S.getLangOptions().CPlusPlus) {
+      // If we're resolving to a reference type, the type of the
+      // expression is the pointee type, and we need to use a
+      // different cast kind so that we know to do the extra load.
+      if (const ReferenceType *refTy = type->getAs<ReferenceType>()) {
+        type = refTy->getPointeeType();
+        castKind = CK_ResolveUnknownAnyTypeToReference;
+      }
+    } else if (type->isFunctionType()) {
+      // Function references aren't l-values in C.
+      valueKind = VK_RValue;
+    }
+
+  //  - nothing else
+  } else {
+    S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl)
+      << decl << expr->getSourceRange();
+    return ExprError();
+  }
+
+  return S.Owned(ImplicitCastExpr::Create(S.Context, type, castKind,
+                                          expr, 0, valueKind));
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitMemberExpr(MemberExpr *mem) {
+  NamedDecl *decl = mem->getMemberDecl();
+  CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl);
+  if (!method || !method->isInstance())
+    return resolveDecl(mem, decl);
+
+  // Rebuild instance-method references as applications of .* or ->*.
+  Expr *base = mem->getBase();
+
+  assert(DestType->isFunctionType());
+
+  // Make a decl ref.
+  TemplateArgumentListInfo explicitArgs;
+  mem->copyTemplateArgumentsInto(explicitArgs);
+  Expr *rhs = DeclRefExpr::Create(S.Context, mem->getQualifierLoc(),
+                                  method, mem->getMemberNameInfo(),
+                                  method->getType(), VK_RValue, &explicitArgs);
+
+  // Turn that into a member pointer constant.
+  const Type *recordTy =
+    S.Context.getTypeDeclType(method->getParent()).getTypePtr();
+  QualType mpt = S.Context.getMemberPointerType(method->getType(), recordTy);
+  rhs = new (S.Context) UnaryOperator(rhs, UO_AddrOf, mpt, VK_RValue,
+                                      OK_Ordinary, SourceLocation());
+
+  // Resolve that.
+  rhs = ImplicitCastExpr::Create(S.Context,
+                          S.Context.getMemberPointerType(DestType, recordTy),
+                                 CK_ResolveUnknownAnyType, rhs, 0, VK_RValue);
+
+  // Turn that into a binary .* or ->*.
+  Expr *result = new (S.Context) BinaryOperator(base, rhs,
+                                    mem->isArrow() ? BO_PtrMemI : BO_PtrMemD,
+                                                DestType, VK_RValue,
+                                                OK_Ordinary, SourceLocation());
+
+  return S.Owned(result);
 }
 
 /// Check a cast of an unknown-any type.  We intentionally only
@@ -10295,18 +10466,37 @@
 
 static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) {
   Expr *orig = e;
+  unsigned diagID = diag::err_uncasted_use_of_unknown_any;
   while (true) {
     e = e->IgnoreParenImpCasts();
-    if (CallExpr *call = dyn_cast<CallExpr>(e))
+    if (CallExpr *call = dyn_cast<CallExpr>(e)) {
       e = call->getCallee();
-    else
+      diagID = diag::err_uncasted_call_of_unknown_any;
+    } else {
       break;
+    }
+  }
+
+  SourceLocation loc;
+  NamedDecl *d;
+  if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
+    loc = ref->getLocation();
+    d = ref->getDecl();
+  } else if (MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
+    loc = mem->getMemberLoc();
+    d = mem->getMemberDecl();
+  } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(e)) {
+    diagID = diag::err_uncasted_call_of_unknown_any;
+    loc = msg->getSelectorLoc();
+    d = msg->getMethodDecl();
+    assert(d && "unknown method returning __unknown_any?");
+  } else {
+    S.Diag(e->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+      << e->getSourceRange();
+    return ExprError();
   }
 
-  assert(isa<DeclRefExpr>(e) && "unexpected form of unknown-any expression");
-  DeclRefExpr *ref = cast<DeclRefExpr>(e);
-  S.Diag(ref->getLocation(), diag::err_bad_use_of_unknown_any)
-    << ref->getDecl() << orig->getSourceRange();
+  S.Diag(loc, diagID) << d << orig->getSourceRange();
 
   // Never recoverable.
   return ExprError();

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Apr 11 02:02:50 2011
@@ -2177,6 +2177,7 @@
       }
       // Various C++ casts that are not handled yet.
       case CK_ResolveUnknownAnyType:
+      case CK_ResolveUnknownAnyTypeToReference:
       case CK_Dynamic:
       case CK_ToUnion:
       case CK_BaseToDerived:

Modified: cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp Mon Apr 11 02:02:50 2011
@@ -55,3 +55,22 @@
   // CHECK: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
   return (Test7) test7_any(5);
 }
+
+struct Test8 {
+  __unknown_anytype foo();
+  __unknown_anytype foo(int);
+
+  void test();
+};
+void Test8::test() {
+  (int) foo();
+  (int) foo(5);
+  (float) this->foo();
+  (float) this->foo(5);
+}
+void test8(Test8 *p) {
+  (double) p->foo();
+  (double) p->foo(5);
+  (bool) (*p).foo();
+  (bool) (*p).foo(5);
+}

Modified: cfe/trunk/test/SemaCXX/unknown-anytype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-anytype.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/SemaCXX/unknown-anytype.cpp Mon Apr 11 02:02:50 2011
@@ -15,7 +15,14 @@
     // properly.
 
     int x = foo; // expected-error {{cannot initialize}}
-    int y = 0 + foo; // expected-error {{no known type for 'foo'; must explicitly cast this expression to use it}}
+    int y = 0 + foo; // expected-error {{'foo' has unknown type}}
     return foo; // expected-error {{cannot initialize}}
   }
 }
+
+namespace test2 {
+  extern __unknown_anytype foo();
+  void test() {
+    foo(); // expected-error {{'foo' has unknown return type}}
+  }
+}





More information about the cfe-commits mailing list