aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-04-07 08:22:57 +0000
committerJohn McCall <rjmccall@apple.com>2011-04-07 08:22:57 +0000
commit1de4d4e8cb2e9c88809fea8092bc6e835a5473d2 (patch)
tree882a7f7c98e0dd8f015d2d7364c941026ecd19c2 /lib
parent1a7f7526b7fd817e3f49c210302d189eff981b5e (diff)
Basic, untested implementation for an "unknown any" type requested by LLDB.
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
Diffstat (limited to 'lib')
-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
21 files changed, 271 insertions, 39 deletions
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);
+
+ 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: