diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1bf13f6437..c330f4cda2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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, diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a6c3d49a2f..110c4a7323 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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!"); diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 35c72c45ce..ab9d97dbb7 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -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) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index f2ec27fe31..97d3d0f35b 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -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; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1abffabf8a..233fe94c43 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9af8f2cb71..6adf844c97 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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. diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 68fd91d4c0..17cb9efcea 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -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 diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e208bfdf1d..01e8f8e396 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index c92087d85f..3cc9670c34 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -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! diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 59de3fe6ee..28f42124f9 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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!"); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index cdd7efaaf5..e0f9958298 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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: { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 6ab68dbae9..be17ccf2d8 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -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; diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 4bf7f23a0a..5b4dc5a191 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -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; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 3224f642bc..b0726e4275 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1132,6 +1132,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const { case NullPtr: return "nullptr_t"; case Overload: return ""; case Dependent: return ""; + case UnknownAny: return ""; case ObjCId: return "id"; case ObjCClass: return "Class"; case ObjCSel: return "SEL"; diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 0873e837d8..cc64830428 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -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: diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 92e6a19c25..a35f81ca20 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1930,6 +1930,12 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { ConvertType(ToType)); return MakeAddrLValue(V, E->getType()); } + case CK_ResolveUnknownAnyType: { + const DeclRefExpr *declRef = cast(E->getSubExpr()); + llvm::Constant *addr = CGM.getAddrOfUnknownAnyDecl(declRef->getDecl(), + E->getType()); + return MakeAddrLValue(addr, E->getType()); + } } llvm_unreachable("Unhandled lvalue cast kind?"); diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index eb64996bd3..75e3a7879d 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -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: diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 3a2fb9bd9d..822a999b96 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -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. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 97effaa515..a3c765e352 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -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)); diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index e276d98f12..0726641030 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -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: diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 34f594ecaa..fe8462bc7c 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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(decl)) + global = GlobalDecl(cast(decl)); + else + global = GlobalDecl(cast(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(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(decl) && cast(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); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 0f86257757..b29437d962 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -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. diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index b9acbc4e9b..13aa23d8d0 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -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: { diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index d10042ad03..e519d1db17 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -1590,3 +1590,4 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, return tcr != TC_Success; } + diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 13ac32dcb1..b62b2eeff1 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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 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()) { // 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()) { FuncT = BPT->getPointeeType()->castAs(); } 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 lhsResult = CheckPlaceholderExpr(LHS, QuestionLoc); + if (!lhsResult.isUsable()) return QualType(); + LHS = lhsResult.take(); - ExprResult RHSResult = CheckPlaceholderExpr(RHS, QuestionLoc); - if (RHSResult.isInvalid()) - return QualType(); - - 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 == 0; // resolve f blindly // void (*p)(int); p = f; // resolve f 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 { + + 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(); + 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(e)) + e = call->getCallee(); + else + break; + } + + assert(isa(e) && "unexpected form of unknown-any expression"); + DeclRefExpr *ref = cast(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(); - 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); } diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index 5e94f59ad4..b5bbe74ce3 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -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; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 1b55f71c36..4cbb81d1ac 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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; diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index a422428b1b..2fd7b3b88a 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -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: diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 834b8d6e89..8d39af10af 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -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 '')}} + y << x.i; // expected-error{{cannot resolve overloaded function 'i' from context}} } } diff --git a/test/SemaTemplate/resolve-single-template-id.cpp b/test/SemaTemplate/resolve-single-template-id.cpp index 7f5d471b90..ff6f37f2bd 100644 --- a/test/SemaTemplate/resolve-single-template-id.cpp +++ b/test/SemaTemplate/resolve-single-template-id.cpp @@ -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 void twoT() { } // expected-note 3{{candidate}} -template void twoT(int) { } // expected-note 3{{candidate}} +template void twoT() { } // expected-note 5{{candidate}} +template void twoT(int) { } // expected-note 5{{candidate}} template void oneT() { } template void oneT(U) { } @@ -51,7 +51,7 @@ int main() void (*p1)(int); p1 = oneT; int i = (int) (false ? (void (*)(int))twoT : oneT); //expected-error {{incompatible operand}} - (twoT) == oneT; //expected-error {{invalid operands to binary expression}} + (twoT) == oneT; //expected-error {{cannot resolve overloaded function 'twoT' from context}} bool b = oneT; void (*p)() = oneT; test > ti; @@ -65,8 +65,8 @@ int main() oneT < oneT; //expected-warning {{self-comparison always evaluates to false}} \ //expected-warning {{expression result unused}} - two < two; //expected-error {{invalid operands to binary expression}} - twoT < twoT; //expected-error {{invalid operands to binary expression}} + two < two; //expected-error {{cannot resolve overloaded function 'two' from context}} + twoT < twoT; //expected-error {{cannot resolve overloaded function 'twoT' from context}} oneT == 0; // expected-warning {{expression result unused}} } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 0978f1b281..80fc7551d7 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -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: diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index e74d1d4deb..91bb802dd1 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -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: