aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h3
-rw-r--r--include/clang/AST/Expr.h1
-rw-r--r--include/clang/AST/OperationKinds.h5
-rw-r--r--include/clang/AST/Type.h11
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Sema/Sema.h4
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--lib/AST/ASTContext.cpp3
-rw-r--r--lib/AST/ASTImporter.cpp1
-rw-r--r--lib/AST/Expr.cpp2
-rw-r--r--lib/AST/ExprConstant.cpp2
-rw-r--r--lib/AST/ItaniumMangle.cpp1
-rw-r--r--lib/AST/MicrosoftMangle.cpp1
-rw-r--r--lib/AST/Type.cpp1
-rw-r--r--lib/AST/TypeLoc.cpp1
-rw-r--r--lib/CodeGen/CGExpr.cpp6
-rw-r--r--lib/CodeGen/CGExprAgg.cpp4
-rw-r--r--lib/CodeGen/CGExprConstant.cpp1
-rw-r--r--lib/CodeGen/CGExprScalar.cpp3
-rw-r--r--lib/CodeGen/CGRTTI.cpp1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp50
-rw-r--r--lib/CodeGen/CodeGenModule.h2
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp5
-rw-r--r--lib/Sema/SemaCXXCast.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp220
-rw-r--r--lib/Serialization/ASTCommon.cpp1
-rw-r--r--lib/Serialization/ASTReader.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp3
-rw-r--r--test/SemaCXX/overloaded-operator.cpp7
-rw-r--r--test/SemaTemplate/resolve-single-template-id.cpp14
-rw-r--r--tools/libclang/CIndex.cpp1
-rw-r--r--tools/libclang/CIndexUSRs.cpp1
32 files changed, 308 insertions, 56 deletions
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 "<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";
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<DeclRefExpr>(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<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);
}
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<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);
+