[cfe-commits] r129331 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/CodeGen/ lib/Sema/ lib/StaticAnalyzer/Core/ test/CodeGenCXX/ test/SemaCXX/

John McCall rjmccall at apple.com
Mon Apr 11 17:42:48 PDT 2011


Author: rjmccall
Date: Mon Apr 11 19:42:48 2011
New Revision: 129331

URL: http://llvm.org/viewvc/llvm-project?rev=129331&view=rev
Log:
After some discussion with Doug, we decided that it made a lot more sense
for __unknown_anytype resolution to destructively modify the AST.  So that's
what it does now, which significantly simplifies some of the implementation.
Normal member calls work pretty cleanly now, and I added support for
propagating unknown-ness through &.


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/ExprClassification.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/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Apr 11 19:42:48 2011
@@ -2221,8 +2221,6 @@
     case CK_MemberPointerToBoolean:
     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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OperationKinds.h (original)
+++ cfe/trunk/include/clang/AST/OperationKinds.h Mon Apr 11 19:42:48 2011
@@ -245,13 +245,7 @@
 
   /// \brief Converts from an integral complex to a floating complex.
   ///   _Complex unsigned -> _Complex float
-  CK_IntegralComplexToFloatingComplex,
-
-  /// \brief Assign an unknown-any declaration a type.
-  CK_ResolveUnknownAnyType,
-
-  /// \brief Assign an unknown-any declaration a reference type.
-  CK_ResolveUnknownAnyTypeToReference
+  CK_IntegralComplexToFloatingComplex
 };
 
 #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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 11 19:42:48 2011
@@ -3859,6 +3859,13 @@
   "%0 has unknown type, which is unsupported for this kind of declaration">;
 def err_unsupported_unknown_any_expr : Error<
   "unsupported expression with unknown type">;
+def err_unsupported_unknown_any_call : Error<
+  "call to unsupported expression with unknown type">;
+def err_unknown_any_addrof : Error<
+  "the address of a declaration with unknown type "
+  "can only be cast to a pointer type">;
+def err_unknown_any_var_function_type : Error<
+  "variable %0 with unknown type cannot be given a function 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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Apr 11 19:42:48 2011
@@ -1055,10 +1055,6 @@
     return "IntegralComplexCast";
   case CK_IntegralComplexToFloatingComplex:
     return "IntegralComplexToFloatingComplex";
-  case CK_ResolveUnknownAnyType:
-    return "ResolveUnknownAnyType";
-  case CK_ResolveUnknownAnyTypeToReference:
-    return "ResolveUnknownAnyTypeToReference";
   }
 
   llvm_unreachable("Unhandled cast kind!");

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Mon Apr 11 19:42:48 2011
@@ -170,6 +170,9 @@
     // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
     //   function or variable and a prvalue otherwise.
   case Expr::DeclRefExprClass:
+    if (E->getType() == Ctx.UnknownAnyTy)
+      return isa<FunctionDecl>(cast<DeclRefExpr>(E)->getDecl())
+               ? Cl::CL_PRValue : Cl::CL_LValue;
     return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl());
     // We deal with names referenced from blocks the same way.
   case Expr::BlockDeclRefExprClass:
@@ -375,6 +378,10 @@
 }
 
 static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
+  if (E->getType() == Ctx.UnknownAnyTy)
+    return (isa<FunctionDecl>(E->getMemberDecl())
+              ? Cl::CL_PRValue : Cl::CL_LValue);
+
   // Handle C first, it's easier.
   if (!Ctx.getLangOptions().CPlusPlus) {
     // C99 6.5.2.3p3

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Apr 11 19:42:48 2011
@@ -1798,8 +1798,6 @@
   case CK_GetObjCProperty:
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
-  case CK_ResolveUnknownAnyType:
-  case CK_ResolveUnknownAnyTypeToReference:
     return false;
 
   case CK_LValueToRValue:
@@ -2353,8 +2351,6 @@
   case CK_GetObjCProperty:
   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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Mon Apr 11 19:42:48 2011
@@ -99,8 +99,7 @@
   return GetBogusMemberPointer(CGM, QualType(MPT, 0));
 }
 
-llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
-                                            QualType unknownType) {
+llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
   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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Mon Apr 11 19:42:48 2011
@@ -119,12 +119,7 @@
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
   /// Create a member pointer for the given method.
-  ///
-  /// \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());
+  virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
 
   /// 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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Apr 11 19:42:48 2011
@@ -1792,35 +1792,6 @@
   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,
@@ -1959,13 +1930,6 @@
                                            ConvertType(ToType));
     return MakeAddrLValue(V, 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);
-  }
   }
   
   llvm_unreachable("Unhandled lvalue cast kind?");

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Mon Apr 11 19:42:48 2011
@@ -310,11 +310,6 @@
     llvm_unreachable("should not be emitting lvalue bitcast as rvalue");
     break;
 
-  case CK_ResolveUnknownAnyType:
-  case CK_ResolveUnknownAnyTypeToReference:
-    EmitAggLoadOfLValue(E);
-    break;
-      
   case CK_Dependent:
   case CK_BitCast:
   case CK_ArrayToPointerDecay:

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Apr 11 19:42:48 2011
@@ -552,8 +552,6 @@
     case CK_GetObjCProperty:
     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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Apr 11 19:42:48 2011
@@ -1127,22 +1127,6 @@
     return RV.getScalarVal();
   }
 
-  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:
     assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
     assert(E->isGLValue() && "lvalue-to-rvalue applied to r-value!");

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Apr 11 19:42:48 2011
@@ -1072,54 +1072,6 @@
   return GetOrCreateLLVMGlobal(MangledName, PTy, D);
 }
 
-/// getAddrOfUnknownAnyDecl - Return an llvm::Constant for the address
-/// of a global which was declared with unknown type.  It is possible
-/// for a VarDecl to end up getting resolved to have function type,
-/// which complicates this substantially; on the other hand, these are
-/// always external references, which does simplify the logic a lot.
-llvm::Constant *
-CodeGenModule::getAddrOfUnknownAnyDecl(const NamedDecl *decl, QualType type) {
-  GlobalDecl global;
-
-  // FunctionDecls will always end up with function types, but
-  // VarDecls can end up with them too.
-  if (isa<FunctionDecl>(decl))
-    global = GlobalDecl(cast<FunctionDecl>(decl));
-  else
-    global = GlobalDecl(cast<VarDecl>(decl));
-  llvm::StringRef mangledName = getMangledName(global);
-
-  const llvm::Type *ty = getTypes().ConvertTypeForMem(type);
-  const llvm::PointerType *pty =
-    llvm::PointerType::get(ty, getContext().getTargetAddressSpace(type));
-
-
-  // Check for an existing global value with this name.
-  llvm::GlobalValue *entry = GetGlobalValue(mangledName);
-  if (entry)
-    return llvm::ConstantExpr::getBitCast(entry, pty);
-
-  // If we're creating something with function type, go ahead and
-  // create a function.
-  if (const llvm::FunctionType *fnty = dyn_cast<llvm::FunctionType>(ty)) {
-    llvm::Function *fn = llvm::Function::Create(fnty,
-                                                llvm::Function::ExternalLinkage,
-                                                mangledName, &getModule());
-    return fn;
-
-  // Otherwise, make a global variable.
-  } else {
-    llvm::GlobalVariable *var
-      = new llvm::GlobalVariable(getModule(), ty, false,
-                                 llvm::GlobalValue::ExternalLinkage,
-                                 0, mangledName, 0,
-                                 false, pty->getAddressSpace());
-    if (isa<VarDecl>(decl) && cast<VarDecl>(decl)->isThreadSpecified())
-      var->setThreadLocal(true);
-    return var;
-  }
-}
-
 /// CreateRuntimeVariable - Create a new runtime global variable with the
 /// specified type and name.
 llvm::Constant *

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Apr 11 19:42:48 2011
@@ -358,7 +358,6 @@
   llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
                                      const llvm::Type *Ty = 0);
 
-  llvm::Constant *getAddrOfUnknownAnyDecl(const NamedDecl *D, QualType type);
 
   /// GetAddrOfFunction - Return the address of the given function.  If Ty is
   /// non-null, then this function will use the specified type if it has to

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Apr 11 19:42:48 2011
@@ -78,8 +78,7 @@
 
   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
-  llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
-                                    QualType unknownType);
+  llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
                                         CharUnits offset);
 
@@ -503,8 +502,7 @@
   return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
 }
 
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
-                                                 QualType unknownType) {
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
   assert(MD->isInstance() && "Member function must not be static!");
   MD = MD->getCanonicalDecl();
 
@@ -539,25 +537,20 @@
       MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
     }
   } else {
-    llvm::Constant *addr;
-    if (!unknownType.isNull()) {
-      addr = CGM.getAddrOfUnknownAnyDecl(MD, unknownType);
+    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 {
-      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);
+      // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+      // function type is incomplete.
+      Ty = ptrdiff_t;
     }
+    llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
 
     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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr 11 19:42:48 2011
@@ -2488,6 +2488,16 @@
       break;
 
     case Decl::Function: {
+      const FunctionType *fty = type->castAs<FunctionType>();
+
+      // If we're referring to a function with an __unknown_anytype
+      // result type, make the entire expression __unknown_anytype.
+      if (fty->getResultType() == Context.UnknownAnyTy) {
+        type = Context.UnknownAnyTy;
+        valueKind = VK_RValue;
+        break;
+      }
+
       // Functions are l-values in C++.
       if (getLangOptions().CPlusPlus) {
         valueKind = VK_LValue;
@@ -2499,10 +2509,10 @@
       // used for checking compatibility. Therefore, when referencing
       // the function, we pretend that we don't have the full function
       // type.
-      if (!cast<FunctionDecl>(VD)->hasPrototype())
-        if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>())
-          type = Context.getFunctionNoProtoType(proto->getResultType(),
-                                                proto->getExtInfo());
+      if (!cast<FunctionDecl>(VD)->hasPrototype() &&
+          isa<FunctionProtoType>(fty))
+        type = Context.getFunctionNoProtoType(fty->getResultType(),
+                                              fty->getExtInfo());
 
       // Functions are r-values in C.
       valueKind = VK_RValue;
@@ -2510,6 +2520,16 @@
     }
 
     case Decl::CXXMethod:
+      // If we're referring to a method with an __unknown_anytype
+      // result type, make the entire expression __unknown_anytype.
+      // This should only be possible with a type written directly.
+      if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(VD->getType()))
+        if (proto->getResultType() == Context.UnknownAnyTy) {
+          type = Context.UnknownAnyTy;
+          valueKind = VK_RValue;
+          break;
+        }
+
       // C++ methods are l-values if static, r-values if non-static.
       if (cast<CXXMethodDecl>(VD)->isStatic()) {
         valueKind = VK_LValue;
@@ -2533,8 +2553,7 @@
   return ExprError();
 }
 
-ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
-                                                 tok::TokenKind Kind) {
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
   PredefinedExpr::IdentType IT;
 
   switch (Kind) {
@@ -4532,16 +4551,37 @@
 
   // If this is a variadic call, handle args passed through "...".
   if (CallType != VariadicDoesNotApply) {
-    // Promote the arguments (C99 6.5.2.2p7).
-    for (unsigned i = ArgIx; i != NumArgs; ++i) {
-      ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
-      Invalid |= Arg.isInvalid();
-      AllArgs.push_back(Arg.take());
+
+    // Assume that extern "C" functions with variadic arguments that
+    // return __unknown_anytype aren't *really* variadic.
+    if (Proto->getResultType() == Context.UnknownAnyTy &&
+        FDecl && FDecl->isExternC()) {
+      for (unsigned i = ArgIx; i != NumArgs; ++i) {
+        ExprResult arg;
+        if (isa<ExplicitCastExpr>(Args[i]->IgnoreParens()))
+          arg = DefaultFunctionArrayLvalueConversion(Args[i]);
+        else
+          arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+        Invalid |= arg.isInvalid();
+        AllArgs.push_back(arg.take());
+      }
+
+    // Otherwise do argument promotion, (C99 6.5.2.2p7).
+    } else {
+      for (unsigned i = ArgIx; i != NumArgs; ++i) {
+        ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+        Invalid |= Arg.isInvalid();
+        AllArgs.push_back(Arg.take());
+      }
     }
   }
   return Invalid;
 }
 
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
+
 /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
 /// This provides the location of the left/right parens and a list of comma
 /// locations.
@@ -4602,6 +4642,12 @@
       return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
                                                 RParenLoc));
 
+    if (Fn->getType() == Context.UnknownAnyTy) {
+      ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
+      if (result.isInvalid()) return ExprError();
+      Fn = result.take();
+    }
+
     Expr *NakedFn = Fn->IgnoreParens();
 
     // Determine whether this is a call to an unresolved member function.
@@ -4715,66 +4761,6 @@
   return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0);
 }
 
-/// Given a function expression of unknown-any type, rebuild it to
-/// have a type appropriate for being called with the given arguments,
-/// yielding a value of unknown-any type.
-static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn,
-                                            Expr **args, unsigned numArgs) {
-  // Strip an lvalue-to-rvalue conversion off.
-  if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(fn))
-    if (ice->getCastKind() == CK_LValueToRValue)
-      fn = ice->getSubExpr();
-
-  // Build a simple function type exactly matching the arguments.
-  llvm::SmallVector<QualType, 8> argTypes;
-  argTypes.reserve(numArgs);
-  for (unsigned i = 0; i != numArgs; ++i) {
-    // Require all the sub-expression to not be placeholders.
-    ExprResult result = S.CheckPlaceholderExpr(args[i]);
-    if (result.isInvalid()) return ExprError();
-    args[i] = result.take();
-
-    QualType argType;
-
-    // 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
-  // type.  In the fully resolved expression, this cast will surround
-  // the DeclRefExpr.
-  FunctionProtoType::ExtProtoInfo extInfo;
-  QualType fnType = S.Context.getFunctionType(S.Context.UnknownAnyTy,
-                                              argTypes.data(), numArgs,
-                                              extInfo);
-  fn = ImplicitCastExpr::Create(S.Context, fnType,
-                                CK_ResolveUnknownAnyType,
-                                fn, /*path*/ 0,
-                     (S.getLangOptions().CPlusPlus ? VK_LValue : VK_RValue));
-
-  // Decay that to a pointer.
-  fnType = S.Context.getPointerType(fnType);
-  fn = ImplicitCastExpr::Create(S.Context, fnType,
-                                CK_FunctionToPointerDecay,
-                                fn, /*path*/ 0, VK_RValue);
-
-  return S.Owned(fn);
-}
-
 /// BuildResolvedCallExpr - Build a call to a resolved expression,
 /// i.e. an expression not of \p OverloadTy.  The expression should
 /// unary-convert to an expression of function-pointer or
@@ -4834,11 +4820,10 @@
   } else {
     // Handle calls to expressions of unknown-any type.
     if (Fn->getType() == Context.UnknownAnyTy) {
-      ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn, Args, NumArgs);
+      ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
       if (rewrite.isInvalid()) return ExprError();
       Fn = rewrite.take();
       TheCall->setCallee(Fn);
-      NDecl = FDecl = 0;
       goto retry;
     }
 
@@ -8103,10 +8088,10 @@
     return S.Context.DependentTy;
   if (OrigOp->getType() == S.Context.OverloadTy)
     return S.Context.OverloadTy;
+  if (OrigOp->getType() == S.Context.UnknownAnyTy)
+    return S.Context.UnknownAnyTy;
 
-  ExprResult PR = S.CheckPlaceholderExpr(OrigOp);
-  if (PR.isInvalid()) return QualType();
-  OrigOp = PR.take();
+  assert(!OrigOp->getType()->isPlaceholderType());
 
   // Make sure to ignore parentheses in subsequent checks
   Expr *op = OrigOp->IgnoreParens();
@@ -10159,6 +10144,93 @@
 }
 
 namespace {
+  /// A visitor for rebuilding a call to an __unknown_any expression
+  /// to have an appropriate type.
+  struct RebuildUnknownAnyFunction
+    : StmtVisitor<RebuildUnknownAnyFunction, ExprResult> {
+
+    Sema &S;
+
+    RebuildUnknownAnyFunction(Sema &S) : S(S) {}
+
+    ExprResult VisitStmt(Stmt *S) {
+      llvm_unreachable("unexpected statement!");
+      return ExprError();
+    }
+
+    ExprResult VisitExpr(Expr *expr) {
+      S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_call)
+        << expr->getSourceRange();
+      return ExprError();
+    }
+
+    /// 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) {
+      ExprResult subResult = Visit(expr->getSubExpr());
+      if (subResult.isInvalid()) return ExprError();
+
+      Expr *subExpr = subResult.take();
+      expr->setSubExpr(subExpr);
+      expr->setType(subExpr->getType());
+      expr->setValueKind(subExpr->getValueKind());
+      assert(expr->getObjectKind() == OK_Ordinary);
+      return expr;
+    }
+
+    ExprResult VisitParenExpr(ParenExpr *paren) {
+      return rebuildSugarExpr(paren);
+    }
+
+    ExprResult VisitUnaryExtension(UnaryOperator *op) {
+      return rebuildSugarExpr(op);
+    }
+
+    ExprResult VisitUnaryAddrOf(UnaryOperator *op) {
+      ExprResult subResult = Visit(op->getSubExpr());
+      if (subResult.isInvalid()) return ExprError();
+
+      Expr *subExpr = subResult.take();
+      op->setSubExpr(subExpr);
+      op->setType(S.Context.getPointerType(subExpr->getType()));
+      assert(op->getValueKind() == VK_RValue);
+      assert(op->getObjectKind() == OK_Ordinary);
+      return op;
+    }
+
+    ExprResult resolveDecl(Expr *expr, ValueDecl *decl) {
+      if (!isa<FunctionDecl>(decl)) return VisitExpr(expr);
+
+      expr->setType(decl->getType());
+
+      assert(expr->getValueKind() == VK_RValue);
+      if (S.getLangOptions().CPlusPlus &&
+          !(isa<CXXMethodDecl>(decl) &&
+            cast<CXXMethodDecl>(decl)->isInstance()))
+        expr->setValueKind(VK_LValue);
+
+      return expr;
+    }
+
+    ExprResult VisitMemberExpr(MemberExpr *mem) {
+      return resolveDecl(mem, mem->getMemberDecl());
+    }
+
+    ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
+      return resolveDecl(ref, ref->getDecl());
+    }
+  };
+}
+
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn) {
+  ExprResult result = RebuildUnknownAnyFunction(S).Visit(fn);
+  if (result.isInvalid()) return ExprError();
+  return S.DefaultFunctionArrayConversion(result.take());
+}
+
+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
@@ -10192,7 +10264,7 @@
     /// expression which it shares the type and value kind of.
     template <class T> ExprResult rebuildSugarExpr(T *expr) {
       ExprResult subResult = Visit(expr->getSubExpr());
-      if (!subResult.isUsable()) return ExprError();
+      if (subResult.isInvalid()) return ExprError();
       Expr *subExpr = subResult.take();
       expr->setSubExpr(subExpr);
       expr->setType(subExpr->getType());
@@ -10209,11 +10281,32 @@
       return rebuildSugarExpr(op);
     }
 
+    ExprResult VisitUnaryAddrOf(UnaryOperator *op) {
+      const PointerType *ptr = DestType->getAs<PointerType>();
+      if (!ptr) {
+        S.Diag(op->getOperatorLoc(), diag::err_unknown_any_addrof)
+          << op->getSourceRange();
+        return ExprError();
+      }
+      assert(op->getValueKind() == VK_RValue);
+      assert(op->getObjectKind() == OK_Ordinary);
+      op->setType(DestType);
+
+      // Build the sub-expression as if it were an object of the pointee type.
+      DestType = ptr->getPointeeType();
+      ExprResult subResult = Visit(op->getSubExpr());
+      if (subResult.isInvalid()) return ExprError();
+      op->setSubExpr(subResult.take());
+      return op;
+    }
+
     ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice);
 
-    ExprResult resolveDecl(Expr *expr, NamedDecl *decl);
+    ExprResult resolveDecl(Expr *expr, ValueDecl *decl);
 
-    ExprResult VisitMemberExpr(MemberExpr *mem);
+    ExprResult VisitMemberExpr(MemberExpr *mem) {
+      return resolveDecl(mem, mem->getMemberDecl());
+    }
 
     ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
       return resolveDecl(ref, ref->getDecl());
@@ -10296,63 +10389,34 @@
 }
 
 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());
+  ObjCMethodDecl *method = msg->getMethodDecl();
+  assert(method && "__unknown_anytype message without result type?");
+
+  // Verify that this is a legal result type of a call.
+  if (DestType->isArrayType() || DestType->isFunctionType()) {
+    S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function)
+      << DestType->isFunctionType() << DestType;
+    return ExprError();
   }
 
-  // Change the type of the message.
-  msg->setType(DestType);
-  assert(msg->getValueKind() == VK_RValue);
+  assert(method->getResultType() == S.Context.UnknownAnyTy);
+  method->setResultType(DestType);
 
-  // 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);
-    }
-  }
+  // Change the type of the message.
+  msg->setType(DestType.getNonReferenceType());
+  msg->setValueKind(Expr::getValueKindForType(DestType));
 
-  return S.MaybeBindToTemporary(result);
+  return S.MaybeBindToTemporary(msg);
 }
 
 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.
+  // The only case we should ever see 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);
 
+  ice->setType(DestType);
+
   // Rebuild the sub-expression as the pointee (function) type.
   DestType = DestType->castAs<PointerType>()->getPointeeType();
 
@@ -10363,16 +10427,15 @@
   return S.Owned(ice);
 }
 
-ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *decl) {
+ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *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 (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+    if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(fn))
       if (method->isInstance()) valueKind = VK_RValue;
 
     // This is true because FunctionDecls must always have function
@@ -10385,17 +10448,12 @@
 
   //  - 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;
-      }
+    if (const ReferenceType *refTy = type->getAs<ReferenceType>()) {
+      type = refTy->getPointeeType();
     } else if (type->isFunctionType()) {
-      // Function references aren't l-values in C.
-      valueKind = VK_RValue;
+      S.Diag(expr->getExprLoc(), diag::err_unknown_any_var_function_type)
+        << decl << expr->getSourceRange();
+      return ExprError();
     }
 
   //  - nothing else
@@ -10405,47 +10463,10 @@
     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);
+  decl->setType(DestType);
+  expr->setType(type);
+  expr->setValueKind(valueKind);
+  return S.Owned(expr);
 }
 
 /// Check a cast of an unknown-any type.  We intentionally only

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Apr 11 19:42:48 2011
@@ -2176,8 +2176,6 @@
         continue;
       }
       // 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=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp Mon Apr 11 19:42:48 2011
@@ -7,21 +7,28 @@
 }
 
 int test1() {
-  extern __unknown_anytype test1_any;
-  // CHECK: call i32 @test1_any()
+  extern __unknown_anytype test1_any();
+  // CHECK: call i32 @_Z9test1_anyv()
   return (int) test1_any();
 }
 
+extern "C" __unknown_anytype test2_any(...);
 float test2() {
-  extern __unknown_anytype test2_any;
-  // CHECK: call float @test2_any(float {{[^,]+}})
+  // CHECK: call float (...)* @test2_any(double {{[^,]+}})
   return (float) test2_any(0.5f);
 }
 
+extern "C" __unknown_anytype test2a_any(...);
+float test2a() {
+  // CHECK: call float (...)* @test2a_any(float {{[^,]+}})
+  return (float) test2a_any((float) 0.5f);
+}
+
 float test3() {
   extern __unknown_anytype test3_any;
-  // CHECK: call float @test3_any(i32 5)
-  return ((float(int)) test3_any)(5);
+  // CHECK: [[FN:%.*]] = load float (i32)** @test3_any,
+  // CHECK: call float [[FN]](i32 5)
+  return ((float(*)(int)) test3_any)(5);
 }
 
 namespace test4 {
@@ -30,28 +37,28 @@
 
   int test() {
     // CHECK: load i32* @_ZN5test410test4_any1E
-    // CHECK: call i32 @_ZN5test410test4_any2E
-    return (int) test4_any1 + (int) test4_any2();
+    // CHECK: load i8* @_ZN5test410test4_any2E
+    return (int) test4_any1 + (char) test4_any2;
   }
 }
 
+extern "C" __unknown_anytype test5_any();
 void test5() {
-  extern __unknown_anytype test5_any;
   // CHECK: call void @test5_any()
   return (void) test5_any();
 }
 
+extern "C" __unknown_anytype test6_any(float *);
 long test6() {
-  extern __unknown_anytype test6_any(float *);
-  // CHECK: call i64 @_Z9test6_anyPf(float* null)
+  // CHECK: call i64 @test6_any(float* null)
   return (long) test6_any(0);
 }
 
 struct Test7 {
   ~Test7();
 };
+extern "C" __unknown_anytype test7_any(int);
 Test7 test7() {
-  extern __unknown_anytype test7_any;
   // CHECK: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
   return (Test7) test7_any(5);
 }
@@ -63,14 +70,30 @@
   void test();
 };
 void Test8::test() {
-  (int) foo();
-  (int) foo(5);
-  (float) this->foo();
-  (float) this->foo(5);
+  float f;
+  // CHECK: call i32 @_ZN5Test83fooEv(
+  f = (int) foo();
+  // CHECK: call i32 @_ZN5Test83fooEi(
+  f = (int) foo(5);
+  // CHECK: call i32 @_ZN5Test83fooEv(
+  f = (float) this->foo();
+  // CHECK: call i32 @_ZN5Test83fooEi(
+  f = (float) this->foo(5);
 }
 void test8(Test8 *p) {
-  (double) p->foo();
-  (double) p->foo(5);
-  (bool) (*p).foo();
-  (bool) (*p).foo(5);
+  double d;
+  // CHECK: call i32 @_ZN5Test83fooEv(
+  d = (double) p->foo();
+  // CHECK: call i32 @_ZN5Test83fooEi(
+  d = (double) p->foo(5);
+  // CHECK: call i32 @_ZN5Test83fooEv(
+  d = (bool) (*p).foo();
+  // CHECK: call i32 @_ZN5Test83fooEi(
+  d = (bool) (*p).foo(5);
+}
+
+extern "C" __unknown_anytype test9_foo;
+void *test9() {
+  // CHECK: ret i8* bitcast (i32* @test9_foo to i8*)
+  return (int*) &test9_foo;
 }

Modified: cfe/trunk/test/SemaCXX/unknown-anytype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-anytype.cpp?rev=129331&r1=129330&r2=129331&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/SemaCXX/unknown-anytype.cpp Mon Apr 11 19:42:48 2011
@@ -26,3 +26,11 @@
     foo(); // expected-error {{'foo' has unknown return type}}
   }
 }
+
+namespace test3 {
+  extern __unknown_anytype foo;
+  void test() {
+    foo(); // expected-error {{call to unsupported expression with unknown type}}
+    ((void(void)) foo)(); // expected-error {{variable 'foo' with unknown type cannot be given a function type}}
+  }
+}





More information about the cfe-commits mailing list