diff options
-rw-r--r-- | include/clang/AST/Expr.h | 2 | ||||
-rw-r--r-- | include/clang/AST/OperationKinds.h | 8 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 7 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 4 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 7 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 36 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 16 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 48 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 1 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 35 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 379 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/unknown-anytype.cpp | 63 | ||||
-rw-r--r-- | test/SemaCXX/unknown-anytype.cpp | 8 |
19 files changed, 282 insertions, 355 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 3879c48e9a..a6c3d49a2f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2221,8 +2221,6 @@ private: 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!"); diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 25598ff88b..35c72c45ce 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -245,13 +245,7 @@ enum CastKind { /// \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) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9dfd2c8a29..1dc3282c75 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3859,6 +3859,13 @@ def err_unsupported_unknown_any_decl : Error< "%0 has unknown type, which is unsupported for this kind of declaration">; def err_unsupported_unknown_any_expr : Error< "unsupported expression with unknown type">; +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 diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 1598227249..59de3fe6ee 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1055,10 +1055,6 @@ const char *CastExpr::getCastKindName() const { return "IntegralComplexCast"; case CK_IntegralComplexToFloatingComplex: return "IntegralComplexToFloatingComplex"; - case CK_ResolveUnknownAnyType: - return "ResolveUnknownAnyType"; - case CK_ResolveUnknownAnyTypeToReference: - return "ResolveUnknownAnyTypeToReference"; } llvm_unreachable("Unhandled cast kind!"); diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index f90d59f505..e94ae82786 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -170,6 +170,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // 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 ClassifyUnnamed(ASTContext &Ctx, QualType T) { } 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 diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index b2f03a21ba..cdd7efaaf5 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1798,8 +1798,6 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { case CK_GetObjCProperty: case CK_LValueBitCast: case CK_UserDefinedConversion: - case CK_ResolveUnknownAnyType: - case CK_ResolveUnknownAnyTypeToReference: return false; case CK_LValueToRValue: @@ -2353,8 +2351,6 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { case CK_GetObjCProperty: case CK_LValueBitCast: case CK_UserDefinedConversion: - case CK_ResolveUnknownAnyType: - case CK_ResolveUnknownAnyTypeToReference: return false; case CK_FloatingRealToComplex: { diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index e8b6f56724..92f1c63a38 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -99,8 +99,7 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 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())); diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index a34ca9bcdc..de4df3dcbe 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -119,12 +119,7 @@ public: 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, diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 496c3fc0aa..92e6a19c25 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1792,35 +1792,6 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) { 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 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { 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?"); diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 5d22fc3304..177d0a4be7 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -310,11 +310,6 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { 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: diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index b04ff0aefb..3a2fb9bd9d 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -552,8 +552,6 @@ public: 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. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index f2ab0a2e06..a44c03ec11 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1127,22 +1127,6 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { 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!"); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 8f304ff580..944b24cbd3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1072,54 +1072,6 @@ 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 * diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index b29437d962..99c973cce6 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -358,7 +358,6 @@ 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 diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 6c864ca7f4..ca3efb5913 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -78,8 +78,7 @@ public: 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 @@ ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 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 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD, 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); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ca06decaf9..be1d666c3a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2488,6 +2488,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, 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 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // 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 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } 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 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, 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 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // 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 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, 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 @@ 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) { - // 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 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } 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 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, 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 @@ ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, } 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 @@ namespace { /// 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 @@ namespace { 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::VisitCallExpr(CallExpr *call) { } ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) { - // This is a long series of hacks around the problem that: - // - we can't just cast the method because it's not an expr, - // - we don't want to modify it in place, and - // - there's no way to override the declared result type - // of a method on a per-call basis. + ObjCMethodDecl *method = msg->getMethodDecl(); + assert(method && "__unknown_anytype message without result type?"); - const ReferenceType *refTy = DestType->getAs<ReferenceType>(); - if (refTy) { - // Hack 1: if we're returning a reference, make the message - // send return a pointer instead. - DestT |