]> granicus.if.org Git - clang/commitdiff
Basic, untested implementation for an "unknown any" type requested by LLDB.
authorJohn McCall <rjmccall@apple.com>
Thu, 7 Apr 2011 08:22:57 +0000 (08:22 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 7 Apr 2011 08:22:57 +0000 (08:22 +0000)
The idea is that you can create a VarDecl with an unknown type, or a
FunctionDecl with an unknown return type, and it will still be valid to
access that object as long as you explicitly cast it at every use.  I'm
still going back and forth about how I want to test this effectively, but
I wanted to go ahead and provide a skeletal implementation for the LLDB
folks' benefit and because it also improves some diagnostic goodness for
placeholder expressions.

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

32 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/Expr.h
include/clang/AST/OperationKinds.h
include/clang/AST/Type.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/Expr.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/MicrosoftMangle.cpp
lib/AST/Type.cpp
lib/AST/TypeLoc.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CGRTTI.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/CodeGenTypes.cpp
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaExpr.cpp
lib/Serialization/ASTCommon.cpp
lib/Serialization/ASTReader.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/SemaCXX/overloaded-operator.cpp
test/SemaTemplate/resolve-single-template-id.cpp
tools/libclang/CIndex.cpp
tools/libclang/CIndexUSRs.cpp

index 1bf13f64372ad3a1450173fb511e442a1d71f6d4..c330f4cda23bf8bb064750e9985f472913a1a20d 100644 (file)
@@ -420,8 +420,7 @@ public:
   CanQualType FloatTy, DoubleTy, LongDoubleTy;
   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
   CanQualType VoidPtrTy, NullPtrTy;
-  CanQualType OverloadTy;
-  CanQualType DependentTy;
+  CanQualType OverloadTy, DependentTy, UnknownAnyTy;
   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
 
   ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
index a6c3d49a2fe6b5e0b5b810eaae809300ea9e50f9..110c4a73235ae675e92371e5022920f83a660f69 100644 (file)
@@ -2221,6 +2221,7 @@ private:
     case CK_MemberPointerToBoolean:
     case CK_FloatingComplexToBoolean:
     case CK_IntegralComplexToBoolean:
+    case CK_ResolveUnknownAnyType:
     case CK_LValueBitCast:            // -> bool&
     case CK_UserDefinedConversion:    // operator bool()
       assert(path_empty() && "Cast kind should not have a base path!");
index 35c72c45ce7c21ecdefec59c48e4ed1a121779d0..ab9d97dbb794d4e582f66015075c9663faec6d92 100644 (file)
@@ -245,7 +245,10 @@ enum CastKind {
 
   /// \brief Converts from an integral complex to a floating complex.
   ///   _Complex unsigned -> _Complex float
-  CK_IntegralComplexToFloatingComplex
+  CK_IntegralComplexToFloatingComplex,
+
+  /// \brief Assign an unknown-any declaration a type.
+  CK_ResolveUnknownAnyType
 };
 
 #define CK_Invalid ((CastKind) -1)
index f2ec27fe31adc24e6331b67fa2d34b31df78c39a..97d3d0f35b610fc8d36d6df6262ef7cc207bd067 100644 (file)
@@ -1488,7 +1488,14 @@ public:
     /// theoretically deducible.
     Dependent,
 
-    Overload,  // This represents the type of an overloaded function declaration.
+    /// The type of an unresolved overload set.
+    Overload,
+
+    /// __builtin_any_type.  Useful for clients like debuggers
+    /// that don't know what type to give something.  Only a small
+    /// number of operations are valid on expressions of unknown type;
+    /// notable among them, calls and explicit casts.
+    UnknownAny,
 
     /// The primitive Objective C 'id' type.  The type pointed to by the
     /// user-visible 'id' type.  Only ever shows up in an AST as the base
@@ -1537,7 +1544,7 @@ public:
   /// i.e. a type which cannot appear in arbitrary positions in a
   /// fully-formed expression.
   bool isPlaceholderType() const {
-    return getKind() == Overload;
+    return getKind() == Overload || getKind() == UnknownAny;
   }
 
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
index 1abffabf8a7654f1ef1f62dbeee820cc40074988..233fe94c43649530dcbedd473b0c46bd8657bfb5 100644 (file)
@@ -3849,6 +3849,9 @@ def err_sizeof_pack_no_pack_name_suggest : Error<
   "%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">;
+
 } // end of sema category
 
 } // end of sema component.
index 9af8f2cb71dd781ff08b3d36cb3d03192d03cd45..6adf844c97e10c71f315d6c59bc8d1bde0466d7f 100644 (file)
@@ -5024,6 +5024,10 @@ public:
                       CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath,
                       bool FunctionalStyle = false);
 
+  bool checkUnknownAnyCast(SourceRange TyRange, QualType castType,
+                           Expr *&castExpr, CastKind &castKind,
+                           ExprValueKind &valueKind, CXXCastPath &BasePath);
+
   // 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.
index 68fd91d4c06961c46373d0f48b5dfa4cfb325e29..17cb9efcea180046d9dbab4a91bcafd6fc27887b 100644 (file)
@@ -490,7 +490,9 @@ namespace clang {
       /// \brief The ObjC 'Class' type.
       PREDEF_TYPE_OBJC_CLASS    = 27,
       /// \brief The ObjC 'SEL' type.
-      PREDEF_TYPE_OBJC_SEL    = 28
+      PREDEF_TYPE_OBJC_SEL      = 28,
+      /// \brief The 'unknown any' type.
+      PREDEF_TYPE_UNKNOWN_ANY   = 29
     };
 
     /// \brief The number of predefined type IDs that are reserved for
index e208bfdf1df5174d1e6a30229e0431c8a9713ed4..01e8f8e396760df4bbd510bf4fca473633777abc 100644 (file)
@@ -402,6 +402,9 @@ void ASTContext::InitBuiltinTypes() {
   // Placeholder type for functions.
   InitBuiltinType(OverloadTy,          BuiltinType::Overload);
 
+  // "any" type; useful for debugger-like clients.
+  InitBuiltinType(UnknownAnyTy,        BuiltinType::UnknownAny);
+
   // C99 6.2.5p11.
   FloatComplexTy      = getComplexType(FloatTy);
   DoubleComplexTy     = getComplexType(DoubleTy);
index c92087d85fd4d7d4496cb1bbc3afa2e1b54f93b5..3cc9670c34425f7db0c22214b17628f1c2603424 100644 (file)
@@ -1360,6 +1360,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
     
   case BuiltinType::Overload: return Importer.getToContext().OverloadTy;
   case BuiltinType::Dependent: return Importer.getToContext().DependentTy;
+  case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy;
 
   case BuiltinType::ObjCId:
     // FIXME: Make sure that the "to" context supports Objective-C!
index 59de3fe6eec037fc17744a5b6c9450dabb12bc4f..28f42124f984189885af0125283efc60a9741272 100644 (file)
@@ -1055,6 +1055,8 @@ const char *CastExpr::getCastKindName() const {
     return "IntegralComplexCast";
   case CK_IntegralComplexToFloatingComplex:
     return "IntegralComplexToFloatingComplex";
+  case CK_ResolveUnknownAnyType:
+    return "ResolveUnknownAnyType";
   }
 
   llvm_unreachable("Unhandled cast kind!");
index cdd7efaaf555561c1608710ba167d95468f30353..e0f995829820fc436382917500b451f58b1a53cc 100644 (file)
@@ -1798,6 +1798,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
   case CK_GetObjCProperty:
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
+  case CK_ResolveUnknownAnyType:
     return false;
 
   case CK_LValueToRValue:
@@ -2351,6 +2352,7 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) {
   case CK_GetObjCProperty:
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
+  case CK_ResolveUnknownAnyType:
     return false;
 
   case CK_FloatingRealToComplex: {
index 6ab68dbae92586d96cc4a4d6f7d58b3d8e056bf2..be17ccf2d823384e6bc8d2b75d046da473bfc7ab 100644 (file)
@@ -1327,6 +1327,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
 
   case BuiltinType::Overload:
   case BuiltinType::Dependent:
+  case BuiltinType::UnknownAny:
     assert(false &&
            "Overloaded and dependent types shouldn't get to name mangling");
     break;
index 4bf7f23a0a9d709e9776593023ba1be19b66b9c5..5b4dc5a1913d6bc4bc22a5d2fbf9c94da971c493 100644 (file)
@@ -717,6 +717,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) {
 
   case BuiltinType::Overload:
   case BuiltinType::Dependent:
+  case BuiltinType::UnknownAny:
     assert(false &&
            "Overloaded and dependent types shouldn't get to name mangling");
     break;
index 3224f642bc6f396ee9df00f3e2bf21a0edd4c746..b0726e427564741abdcffd320af9dff62b72414c 100644 (file)
@@ -1132,6 +1132,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const {
   case NullPtr:           return "nullptr_t";
   case Overload:          return "<overloaded function type>";
   case Dependent:         return "<dependent type>";
+  case UnknownAny:        return "<unknown type>";
   case ObjCId:            return "id";
   case ObjCClass:         return "Class";
   case ObjCSel:           return "SEL";
index 0873e837d8209667d904b65c23d2ba51f494f308..cc6483042859ebb5ccd09d6b54a39796cbbc0c46 100644 (file)
@@ -234,6 +234,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
     case BuiltinType::NullPtr:
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
+    case BuiltinType::UnknownAny:
     case BuiltinType::ObjCId:
     case BuiltinType::ObjCClass:
     case BuiltinType::ObjCSel:
index 92e6a19c25d660057d3e75f65a7f19009ce85fdc..a35f81ca206665c77ad1e0b25dff39f9aa67c8d8 100644 (file)
@@ -1930,6 +1930,12 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
                                            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());
+  }
   }
   
   llvm_unreachable("Unhandled lvalue cast kind?");
index eb64996bd335693078dbd5cd43acb86fdb8aef3d..75e3a7879d42046c28642ea38e879e9ac69e3063 100644 (file)
@@ -309,6 +309,10 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
   case CK_LValueBitCast:
     llvm_unreachable("should not be emitting lvalue bitcast as rvalue");
     break;
+
+  case CK_ResolveUnknownAnyType:
+    EmitAggLoadOfLValue(E);
+    break;
       
   case CK_Dependent:
   case CK_BitCast:
index 3a2fb9bd9d4b5066f3bffabdaece582ca4c83028..822a999b963d6af1a0f17ec14db4e2f2f31d5558 100644 (file)
@@ -552,6 +552,7 @@ public:
     case CK_GetObjCProperty:
     case CK_ToVoid:
     case CK_Dynamic:
+    case CK_ResolveUnknownAnyType:
       return 0;
 
     // These might need to be supported for constexpr.
index 97effaa5158a5cc35ff4a1928c582eb399120142..a3c765e35280f26ded83e9c90373c6ca7d8a4f32 100644 (file)
@@ -1126,6 +1126,9 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
     RValue RV = CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType());
     return RV.getScalarVal();
   }
+
+  case CK_ResolveUnknownAnyType:
+    return EmitLoadOfLValue(CE);
       
   case CK_LValueToRValue:
     assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
index e276d98f12adaa66d0684b41e58cf01457743062..07266410300dd1474392c6d42f0170b8a00f5dcb 100644 (file)
@@ -196,6 +196,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
       
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
+    case BuiltinType::UnknownAny:
       assert(false && "Should not see this type here!");
       
     case BuiltinType::ObjCId:
index 34f594ecaa9c186b4038b6b59866ff0233be45dc..fe8462bc7c2ed66cbb5a4cd501207bc4373d5016 100644 (file)
@@ -1072,12 +1072,60 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
   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 *
 CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,
                                      llvm::StringRef Name) {
-  return GetOrCreateLLVMGlobal(Name,  llvm::PointerType::getUnqual(Ty), 0,
+  return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0,
                                true);
 }
 
index 0f86257757d7fd5e0ef6598303adb86d68f07f33..b29437d9620221d90302391c67218d0305eed0ae 100644 (file)
@@ -358,6 +358,8 @@ public:
   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
   /// create it.
index b9acbc4e9b60401ce3d18eff29008e01ef622739..13aa23d8d0d9d0d5cb41822cc66cc546210d6444 100644 (file)
@@ -253,10 +253,11 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
     
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
-      assert(0 && "Unexpected builtin type!");
+    case BuiltinType::UnknownAny:
+      llvm_unreachable("Unexpected builtin type!");
       break;
     }
-    assert(0 && "Unknown builtin type!");
+    llvm_unreachable("Unknown builtin type!");
     break;
   }
   case Type::Complex: {
index d10042ad0349818bcbb0d747fbff0da0cb5809ac..e519d1db17ffa6a3d32b927f83924bd359d2c5f2 100644 (file)
@@ -1590,3 +1590,4 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
 
   return tcr != TC_Success;
 }
+
index 13ac32dcb13cf2ebcaccc73468a439be81e376cb..b62b2eeff1da50c6a8937f9b63a876ca8344b2ab 100644 (file)
@@ -4658,6 +4658,47 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
   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) {
+  // 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], SourceLocation());
+    if (result.isInvalid()) return ExprError();
+    args[i] = result.take();
+
+    // Do l2r conversions on all the arguments.
+    S.DefaultLvalueConversion(args[i]);
+
+    argTypes.push_back(args[i]->getType());
+  }
+
+  // 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
@@ -4699,6 +4740,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
   if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
     return CheckBuiltinFunctionCall(BuiltinID, TheCall);
 
+ retry:
   const FunctionType *FuncT;
   if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
     // C99 6.5.2.2p1 - "The expression that denotes the called function shall
@@ -4711,6 +4753,15 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
                Fn->getType()->getAs<BlockPointerType>()) {
     FuncT = BPT->getPointeeType()->castAs<FunctionType>();
   } else {
+    // Handle calls to expressions of unknown-any type.
+    if (Fn->getType() == Context.UnknownAnyTy) {
+      ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn, Args, NumArgs);
+      if (rewrite.isInvalid()) return ExprError();
+      Fn = rewrite.take();
+      NDecl = FDecl = 0;
+      goto retry;
+    }
+
     return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
       << Fn->getType() << Fn->getSourceRange());
   }
@@ -5038,6 +5089,9 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
 bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
                           Expr *&castExpr, CastKind& Kind, ExprValueKind &VK,
                           CXXCastPath &BasePath, bool FunctionalStyle) {
+  if (castExpr->getType() == Context.UnknownAnyTy)
+    return checkUnknownAnyCast(TyR, castType, castExpr, Kind, VK, BasePath);
+
   if (getLangOptions().CPlusPlus)
     return CXXCheckCStyleCast(SourceRange(TyR.getBegin(),
                                           castExpr->getLocEnd()), 
@@ -5398,19 +5452,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
                                         SourceLocation QuestionLoc) {
 
   // If either LHS or RHS are overloaded functions, try to resolve them.
-  if (LHS->getType() == Context.OverloadTy || 
-      RHS->getType() == Context.OverloadTy) {
-    ExprResult LHSResult = CheckPlaceholderExpr(LHS, QuestionLoc);
-    if (LHSResult.isInvalid())
-      return QualType();
-
-    ExprResult RHSResult = CheckPlaceholderExpr(RHS, QuestionLoc);
-    if (RHSResult.isInvalid())
-      return QualType();
+  ExprResult lhsResult = CheckPlaceholderExpr(LHS, QuestionLoc);
+  if (!lhsResult.isUsable()) return QualType();
+  LHS = lhsResult.take();
 
-    LHS = LHSResult.take();
-    RHS = RHSResult.take();
-  }
+  ExprResult rhsResult = CheckPlaceholderExpr(RHS, QuestionLoc);
+  if (!rhsResult.isUsable()) return QualType();
+  RHS = rhsResult.take();
 
   // C++ is sufficiently different to merit its own checker.
   if (getLangOptions().CPlusPlus)
@@ -8161,16 +8209,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
   // f<int> == 0;  // resolve f<int> blindly
   // void (*p)(int); p = f<int>;  // resolve f<int> using target
   if (Opc != BO_Assign) { 
-    if (lhs->getType() == Context.OverloadTy) {
-      ExprResult resolvedLHS = 
-        ResolveAndFixSingleFunctionTemplateSpecialization(lhs);
-      if (resolvedLHS.isUsable()) lhs = resolvedLHS.release(); 
-    }
-    if (rhs->getType() == Context.OverloadTy) {
-      ExprResult resolvedRHS = 
-        ResolveAndFixSingleFunctionTemplateSpecialization(rhs);
-      if (resolvedRHS.isUsable()) rhs = resolvedRHS.release(); 
-    }
+    ExprResult resolvedLHS = CheckPlaceholderExpr(lhs, OpLoc);
+    if (!resolvedLHS.isUsable()) return ExprError();
+    lhs = resolvedLHS.take();
+
+    ExprResult resolvedRHS = CheckPlaceholderExpr(rhs, OpLoc);
+    if (!resolvedRHS.isUsable()) return ExprError();
+    rhs = resolvedRHS.take();
   }
 
   switch (Opc) {
@@ -8529,15 +8574,14 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
   case UO_AddrOf:
     resultType = CheckAddressOfOperand(*this, Input, OpLoc);
     break;
-  case UO_Deref:
-    if (Input->getType() == Context.OverloadTy ) {
-      ExprResult er = ResolveAndFixSingleFunctionTemplateSpecialization(Input);
-      if (er.isUsable())
-        Input = er.release();
-    }
+  case UO_Deref: {
+    ExprResult resolved = CheckPlaceholderExpr(Input, OpLoc);
+    if (!resolved.isUsable()) return ExprError();
+    Input = resolved.take();
     DefaultFunctionArrayLvalueConversion(Input);
     resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc);
     break;
+  }
   case UO_Plus:
   case UO_Minus:
     UsualUnaryConversions(Input);
@@ -9904,16 +9948,122 @@ ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
   return Owned(Sub);
 }
 
+namespace {
+  struct RebuildUnknownAnyExpr
+    : StmtVisitor<RebuildUnknownAnyExpr, Expr*> {
+
+    Sema &S;
+
+    /// The current destination type.
+    QualType DestType;
+
+    RebuildUnknownAnyExpr(Sema &S, QualType castType)
+      : S(S), DestType(castType) {}
+
+    Expr *VisitStmt(Stmt *S) {
+      llvm_unreachable("unexpected expression kind!");
+      return 0;
+    }
+
+    Expr *VisitCallExpr(CallExpr *call) {
+      call->setCallee(Visit(call->getCallee()));
+      return call;
+    }
+
+    Expr *VisitParenExpr(ParenExpr *paren) {
+      paren->setSubExpr(Visit(paren->getSubExpr()));
+      return paren;
+    }
+
+    Expr *VisitUnaryExtension(UnaryOperator *op) {
+      op->setSubExpr(Visit(op->getSubExpr()));
+      return op;
+    }
+
+    Expr *VisitImplicitCastExpr(ImplicitCastExpr *ice) {
+      // If this isn't an inner resolution, just recurse down.
+      if (ice->getCastKind() != CK_ResolveUnknownAnyType) {
+        assert(ice->getCastKind() == CK_FunctionToPointerDecay);
+        ice->setSubExpr(Visit(ice->getSubExpr()));
+        return ice;
+      }
+
+      QualType type = ice->getType();
+      assert(type.getUnqualifiedType() == type);
+
+      // The only time it should be possible for this to appear
+      // internally to an unknown-any expression is when handling a call.
+      const FunctionProtoType *proto = type->castAs<FunctionProtoType>();
+      DestType = S.Context.getFunctionType(DestType,
+                                           proto->arg_type_begin(),
+                                           proto->getNumArgs(),
+                                           proto->getExtProtoInfo());
+
+      // Strip the resolve cast when recursively rebuilding.
+      return Visit(ice->getSubExpr());
+    }
+
+    Expr *VisitDeclRefExpr(DeclRefExpr *ref) {
+      ExprValueKind valueKind = VK_LValue;
+      if (!S.getLangOptions().CPlusPlus && DestType->isFunctionType())
+        valueKind = VK_RValue;
+
+      return ImplicitCastExpr::Create(S.Context, DestType,
+                                      CK_ResolveUnknownAnyType,
+                                      ref, 0, valueKind);
+    }
+  };
+}
+
+/// Check a cast of an unknown-any type.  We intentionally only
+/// trigger this for C-style casts.
+bool Sema::checkUnknownAnyCast(SourceRange typeRange, QualType castType,
+                               Expr *&castExpr, CastKind &castKind,
+                               ExprValueKind &VK, CXXCastPath &path) {
+  VK = Expr::getValueKindForType(castType);
+
+  // Rewrite the casted expression from scratch.
+  castExpr = RebuildUnknownAnyExpr(*this, castType).Visit(castExpr);
+
+  return CheckCastTypes(typeRange, castType, castExpr, castKind, VK, path);
+}
+
+static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) {
+  Expr *orig = e;
+  while (true) {
+    e = e->IgnoreParenImpCasts();
+    if (CallExpr *call = dyn_cast<CallExpr>(e))
+      e = call->getCallee();
+    else
+      break;
+  }
+
+  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();
+
+  // Never recoverable.
+  return ExprError();
+}
+
 /// Check for operands with placeholder types and complain if found.
 /// Returns true if there was an error and no recovery was possible.
 ExprResult Sema::CheckPlaceholderExpr(Expr *E, SourceLocation Loc) {
-  const BuiltinType *BT = E->getType()->getAs<BuiltinType>();
-  if (!BT || !BT->isPlaceholderType()) return Owned(E);
+  // Placeholder types are always *exactly* the appropriate builtin type.
+  QualType type = E->getType();
 
-  // If this is overload, check for a single overload.
-  assert(BT->getKind() == BuiltinType::Overload);
-  return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true,
+  // Overloaded expressions.
+  if (type == Context.OverloadTy)
+    return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true,
                                                            E->getSourceRange(),
-                                                           QualType(),
-                                                    diag::err_ovl_unresolvable);
+                                                             QualType(),
+                                                   diag::err_ovl_unresolvable);
+
+  // Expressions of unknown type.
+  if (type == Context.UnknownAnyTy)
+    return diagnoseUnknownAnyExpr(*this, E);
+
+  assert(!type->isPlaceholderType());
+  return Owned(E);
 }
index 5e94f59ad4932503236aa55955bca55c1170e083..b5bbe74ce3d4d18f9d31c2df570e7614c0134912 100644 (file)
@@ -51,6 +51,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
   case BuiltinType::Char32:     ID = PREDEF_TYPE_CHAR32_ID;     break;
   case BuiltinType::Overload:   ID = PREDEF_TYPE_OVERLOAD_ID;   break;
   case BuiltinType::Dependent:  ID = PREDEF_TYPE_DEPENDENT_ID;  break;
+  case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY;   break;
   case BuiltinType::ObjCId:     ID = PREDEF_TYPE_OBJC_ID;       break;
   case BuiltinType::ObjCClass:  ID = PREDEF_TYPE_OBJC_CLASS;    break;
   case BuiltinType::ObjCSel:    ID = PREDEF_TYPE_OBJC_SEL;      break;
index 1b55f71c36b1da45b5216bc52555edc1b317324b..4cbb81d1ac41253670546ef661ec3e6e2ec7079c 100644 (file)
@@ -3622,6 +3622,7 @@ QualType ASTReader::GetType(TypeID ID) {
     case PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy;       break;
     case PREDEF_TYPE_OVERLOAD_ID:   T = Context->OverloadTy;         break;
     case PREDEF_TYPE_DEPENDENT_ID:  T = Context->DependentTy;        break;
+    case PREDEF_TYPE_UNKNOWN_ANY:   T = Context->UnknownAnyTy;       break;
     case PREDEF_TYPE_NULLPTR_ID:    T = Context->NullPtrTy;          break;
     case PREDEF_TYPE_CHAR16_ID:     T = Context->Char16Ty;           break;
     case PREDEF_TYPE_CHAR32_ID:     T = Context->Char32Ty;           break;
index a422428b1bfd05f63af36b8a8901b47810cb9112..2fd7b3b88a6f52d0988b56effbb15363a5be1964 100644 (file)
@@ -2170,7 +2170,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
         continue;
       }
       // Various C++ casts that are not handled yet.
-      case CK_Dynamic:  
+      case CK_ResolveUnknownAnyType:
+      case CK_Dynamic:
       case CK_ToUnion:
       case CK_BaseToDerived:
       case CK_NullToMemberPointer:
index 834b8d6e893893b76466571d60e87c8c1970c162..8d39af10af0c37fc0a21f61b12b6f9f48fbf7c4b 100644 (file)
@@ -387,8 +387,8 @@ void test_lookup_through_using() {
 
 namespace rdar9136502 {
   struct X {
-    int i();
-    int i(int);
+    int i(); // expected-note {{candidate function}}
+    int i(int); // expected-note {{candidate function}}
   };
 
   struct Y {
@@ -396,7 +396,6 @@ namespace rdar9136502 {
   };
 
   void f(X x, Y y) {
-    // FIXME: This diagnostic is non-awesome.
-    y << x.i; // expected-error{{invalid operands to binary expression ('rdar9136502::Y' and '<overloaded function type>')}}
+    y << x.i; // expected-error{{cannot resolve overloaded function 'i' from context}}
   }
 }
index 7f5d471b90468b6daec8f11a6af7658c3532adc2..ff6f37f2bda32159afc6d3fe8d69f08784f6a24b 100644 (file)
@@ -5,11 +5,11 @@ namespace std {
 }
 
 void one() { }
-void two() { } // expected-note 2{{candidate}}
-void two(int) { } // expected-note 2{{candidate}}
+void two() { } // expected-note 3{{candidate}}
+void two(int) { } // expected-note 3{{candidate}}
 
-template<class T> void twoT() { } // expected-note 3{{candidate}}
-template<class T> void twoT(int) { } // expected-note 3{{candidate}}
+template<class T> void twoT() { } // expected-note 5{{candidate}}
+template<class T> void twoT(int) { } // expected-note 5{{candidate}}
 
 template<class T> void oneT() { }
 template<class T, class U> void oneT(U) { }
@@ -51,7 +51,7 @@ int main()
   void (*p1)(int); p1 = oneT<int>;
   
   int i = (int) (false ? (void (*)(int))twoT<int> : oneT<int>); //expected-error {{incompatible operand}}
-  (twoT<int>) == oneT<int>; //expected-error {{invalid operands to binary expression}}
+  (twoT<int>) == oneT<int>; //expected-error {{cannot resolve overloaded function 'twoT' from context}}
   bool b = oneT<int>;
   void (*p)() = oneT<int>;
   test<oneT<int> > ti;
@@ -65,8 +65,8 @@ int main()
   oneT<int> < oneT<int>;  //expected-warning {{self-comparison always evaluates to false}} \
                           //expected-warning {{expression result unused}}
 
-  two < two; //expected-error {{invalid operands to binary expression}}
-  twoT<int> < twoT<int>; //expected-error {{invalid operands to binary expression}}
+  two < two; //expected-error {{cannot resolve overloaded function 'two' from context}}
+  twoT<int> < twoT<int>; //expected-error {{cannot resolve overloaded function 'twoT' from context}}
   oneT<int> == 0;   // expected-warning {{expression result unused}}
 
 }
index 0978f1b2813854dc90fa115b2751abcd10988aa8..80fc7551d7f7717cc5593ecb1b529df42738a828 100644 (file)
@@ -1393,6 +1393,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
   case BuiltinType::NullPtr:
   case BuiltinType::Overload:
   case BuiltinType::Dependent:
+  case BuiltinType::UnknownAny:
     break;
 
   case BuiltinType::ObjCId:
index e74d1d4deb3f6b1afe273dede6a13e3e015d89c4..91bb802dd1be246ec159cfb1f6ddcebdc04ffc18 100644 (file)
@@ -571,6 +571,7 @@ void USRGenerator::VisitType(QualType T) {
           c = 'n'; break;
         case BuiltinType::Overload:
         case BuiltinType::Dependent:
+        case BuiltinType::UnknownAny:
           IgnoreResults = true;
           return;
         case BuiltinType::ObjCId: