diff options
author | John McCall <rjmccall@apple.com> | 2011-04-09 22:50:59 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-04-09 22:50:59 +0000 |
commit | a5fc472b353b88be3b4981da946fb01f5a5cc0c6 (patch) | |
tree | 6d7bbf117ee1d4f5e5742e5fa1826461d56059ca /lib/Sema | |
parent | 5536daa627b508299007b735a588bf4e88825bb3 (diff) |
Fix a bunch of major problems with __unknown_anytype and properly test
for them. The only major missing feature is references.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129234 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 153 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 4 |
4 files changed, 120 insertions, 39 deletions
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index cad3b58d76..0f20d10b07 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -309,6 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_typeofExpr: return "typeof"; case DeclSpec::TST_auto: return "auto"; case DeclSpec::TST_decltype: return "(decltype)"; + case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_error: return "(error)"; } llvm_unreachable("Unknown typespec!"); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fbf0a986d5..70d7c7af48 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4720,6 +4720,11 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, /// 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); @@ -4818,6 +4823,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn, Args, NumArgs); if (rewrite.isInvalid()) return ExprError(); Fn = rewrite.take(); + TheCall->setCallee(Fn); NDecl = FDecl = 0; goto retry; } @@ -10138,7 +10144,7 @@ ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, namespace { struct RebuildUnknownAnyExpr - : StmtVisitor<RebuildUnknownAnyExpr, Expr*> { + : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> { Sema &S; @@ -10148,57 +10154,123 @@ namespace { RebuildUnknownAnyExpr(Sema &S, QualType castType) : S(S), DestType(castType) {} - Expr *VisitStmt(Stmt *S) { + ExprResult VisitStmt(Stmt *S) { llvm_unreachable("unexpected expression kind!"); - return 0; + return ExprError(); + } + + ExprResult VisitCallExpr(CallExpr *call) { + Expr *callee = call->getCallee(); + + bool wasBlock; + QualType type = callee->getType(); + if (const PointerType *ptr = type->getAs<PointerType>()) { + type = ptr->getPointeeType(); + wasBlock = false; + } else { + type = type->castAs<BlockPointerType>()->getPointeeType(); + wasBlock = true; + } + const FunctionType *fnType = type->castAs<FunctionType>(); + + // Verify that this is a legal result type of a function. + if (DestType->isArrayType() || DestType->isFunctionType()) { + unsigned diagID = diag::err_func_returning_array_function; + if (wasBlock) diagID = diag::err_block_returning_array_function; + + S.Diag(call->getExprLoc(), diagID) + << DestType->isFunctionType() << DestType; + return ExprError(); + } + + // Otherwise, go ahead and set DestType as the call's result. + call->setType(DestType.getNonLValueExprType(S.Context)); + call->setValueKind(Expr::getValueKindForType(DestType)); + assert(call->getObjectKind() == OK_Ordinary); + + // Rebuild the function type, replacing the result type with DestType. + if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) + DestType = S.Context.getFunctionType(DestType, + proto->arg_type_begin(), + proto->getNumArgs(), + proto->getExtProtoInfo()); + else + DestType = S.Context.getFunctionNoProtoType(DestType, + fnType->getExtInfo()); + + // Rebuild the appropriate pointer-to-function type. + if (wasBlock) + DestType = S.Context.getBlockPointerType(DestType); + else + DestType = S.Context.getPointerType(DestType); + + // Finally, we can recurse. + ExprResult calleeResult = Visit(callee); + if (!calleeResult.isUsable()) return ExprError(); + call->setCallee(calleeResult.take()); + + // Bind a temporary if necessary. + return S.MaybeBindToTemporary(call); } - Expr *VisitCallExpr(CallExpr *call) { - call->setCallee(Visit(call->getCallee())); - return call; + /// 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.isUsable()) return ExprError(); + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; } - Expr *VisitParenExpr(ParenExpr *paren) { - paren->setSubExpr(Visit(paren->getSubExpr())); - return paren; + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); } - Expr *VisitUnaryExtension(UnaryOperator *op) { - op->setSubExpr(Visit(op->getSubExpr())); - return op; + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(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; - } + ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice) { + // Rebuild an inner resolution by stripping it and propagating + // the new type down. + if (ice->getCastKind() == CK_ResolveUnknownAnyType) + return Visit(ice->getSubExpr()); + + // The only other case we should be able to get here is a + // function-to-pointer decay. + assert(ice->getCastKind() == CK_FunctionToPointerDecay); + ice->setType(DestType); + assert(ice->getValueKind() == VK_RValue); + assert(ice->getObjectKind() == OK_Ordinary); - QualType type = ice->getType(); - assert(type.getUnqualifiedType() == type); + // Rebuild the sub-expression as the pointee (function) type. + DestType = DestType->castAs<PointerType>()->getPointeeType(); - // 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()); + ExprResult result = Visit(ice->getSubExpr()); + if (!result.isUsable()) return ExprError(); - // Strip the resolve cast when recursively rebuilding. - return Visit(ice->getSubExpr()); + ice->setSubExpr(result.take()); + return S.Owned(ice); } - Expr *VisitDeclRefExpr(DeclRefExpr *ref) { + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { ExprValueKind valueKind = VK_LValue; - if (!S.getLangOptions().CPlusPlus && DestType->isFunctionType()) + if (S.getLangOptions().CPlusPlus) { + // FIXME: if the value was resolved as a reference type, we + // should really remember that somehow, or else we'll be + // missing a load. + DestType = DestType.getNonReferenceType(); + } else if (DestType->isFunctionType()) { valueKind = VK_RValue; + } - return ImplicitCastExpr::Create(S.Context, DestType, - CK_ResolveUnknownAnyType, - ref, 0, valueKind); + return S.Owned(ImplicitCastExpr::Create(S.Context, DestType, + CK_ResolveUnknownAnyType, + ref, 0, valueKind)); } }; } @@ -10208,12 +10280,15 @@ namespace { ExprResult 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); + ExprResult result = RebuildUnknownAnyExpr(*this, castType).Visit(castExpr); + if (!result.isUsable()) return ExprError(); + + castExpr = result.take(); + VK = castExpr->getValueKind(); + castKind = CK_NoOp; - return CheckCastTypes(typeRange, castType, castExpr, castKind, VK, path); + return castExpr; } static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) { diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 0da801c7e3..5c321fd6df 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -649,6 +649,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_struct: case TST_class: case TST_auto: + case TST_unknown_anytype: case TST_error: break; } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 3a19f2f73a..fc2c8f7e1d 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -841,6 +841,10 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { break; } + case DeclSpec::TST_unknown_anytype: + Result = Context.UnknownAnyTy; + break; + case DeclSpec::TST_error: Result = Context.IntTy; declarator.setInvalidType(true); |