[cfe-commits] r129269 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/OperationKinds.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Expr.cpp lib/AST/ExprConstant.cpp lib/CodeGen/CGCXXABI.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/ItaniumCXXABI.cpp lib/Sema/SemaExpr.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/CodeGenCXX/unknown-anytype.cpp test/SemaCXX/unknown-anytype.cpp
John McCall
rjmccall at apple.com
Mon Apr 11 00:02:51 PDT 2011
Author: rjmccall
Date: Mon Apr 11 02:02:50 2011
New Revision: 129269
URL: http://llvm.org/viewvc/llvm-project?rev=129269&view=rev
Log:
More __unknown_anytype work.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/OperationKinds.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp
cfe/trunk/test/SemaCXX/unknown-anytype.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Apr 11 02:02:50 2011
@@ -2222,6 +2222,7 @@
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!");
Modified: cfe/trunk/include/clang/AST/OperationKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OperationKinds.h?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OperationKinds.h (original)
+++ cfe/trunk/include/clang/AST/OperationKinds.h Mon Apr 11 02:02:50 2011
@@ -248,7 +248,10 @@
CK_IntegralComplexToFloatingComplex,
/// \brief Assign an unknown-any declaration a type.
- CK_ResolveUnknownAnyType
+ CK_ResolveUnknownAnyType,
+
+ /// \brief Assign an unknown-any declaration a reference type.
+ CK_ResolveUnknownAnyTypeToReference
};
#define CK_Invalid ((CastKind) -1)
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 11 02:02:50 2011
@@ -3851,8 +3851,14 @@
"%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">;
+def err_uncasted_use_of_unknown_any : Error<
+ "%0 has unknown type; cast it to its declared type to use it">;
+def err_uncasted_call_of_unknown_any : Error<
+ "%0 has unknown return type; cast the call to its declared return type">;
+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">;
} // end of sema category
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Apr 11 02:02:50 2011
@@ -1057,6 +1057,8 @@
return "IntegralComplexToFloatingComplex";
case CK_ResolveUnknownAnyType:
return "ResolveUnknownAnyType";
+ case CK_ResolveUnknownAnyTypeToReference:
+ return "ResolveUnknownAnyTypeToReference";
}
llvm_unreachable("Unhandled cast kind!");
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Apr 11 02:02:50 2011
@@ -1799,6 +1799,7 @@
case CK_LValueBitCast:
case CK_UserDefinedConversion:
case CK_ResolveUnknownAnyType:
+ case CK_ResolveUnknownAnyTypeToReference:
return false;
case CK_LValueToRValue:
@@ -2353,6 +2354,7 @@
case CK_LValueBitCast:
case CK_UserDefinedConversion:
case CK_ResolveUnknownAnyType:
+ case CK_ResolveUnknownAnyTypeToReference:
return false;
case CK_FloatingRealToComplex: {
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Mon Apr 11 02:02:50 2011
@@ -99,7 +99,8 @@
return GetBogusMemberPointer(CGM, QualType(MPT, 0));
}
-llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
+ QualType unknownType) {
return GetBogusMemberPointer(CGM,
CGM.getContext().getMemberPointerType(MD->getType(),
MD->getParent()->getTypeForDecl()));
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Mon Apr 11 02:02:50 2011
@@ -119,7 +119,12 @@
virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
/// Create a member pointer for the given method.
- virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+ ///
+ /// \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());
/// Create a member pointer for the given field.
virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Apr 11 02:02:50 2011
@@ -1792,6 +1792,35 @@
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,
@@ -1930,11 +1959,12 @@
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());
+ 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);
}
}
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Mon Apr 11 02:02:50 2011
@@ -311,6 +311,7 @@
break;
case CK_ResolveUnknownAnyType:
+ case CK_ResolveUnknownAnyTypeToReference:
EmitAggLoadOfLValue(E);
break;
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Mon Apr 11 02:02:50 2011
@@ -167,10 +167,12 @@
// extensions allowing explicit constructor function call.
RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
ReturnValueSlot ReturnValue) {
- if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens()))
+ const Expr *callee = CE->getCallee()->IgnoreParens();
+
+ if (isa<BinaryOperator>(callee))
return EmitCXXMemberPointerCallExpr(CE, ReturnValue);
-
- const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens());
+
+ const MemberExpr *ME = cast<MemberExpr>(callee);
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
CGDebugInfo *DI = getDebugInfo();
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Apr 11 02:02:50 2011
@@ -553,6 +553,7 @@
case CK_ToVoid:
case CK_Dynamic:
case CK_ResolveUnknownAnyType:
+ case CK_ResolveUnknownAnyTypeToReference:
return 0;
// These might need to be supported for constexpr.
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Apr 11 02:02:50 2011
@@ -1128,6 +1128,19 @@
}
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:
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Apr 11 02:02:50 2011
@@ -78,7 +78,8 @@
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
- llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+ llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
+ QualType unknownType);
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset);
@@ -502,7 +503,8 @@
return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
}
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
+ QualType unknownType) {
assert(MD->isInstance() && "Member function must not be static!");
MD = MD->getCanonicalDecl();
@@ -537,20 +539,27 @@
MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
}
} else {
- const FunctionProtoType *FPT = MD->getType()->getAs<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());
+ llvm::Constant *addr;
+ if (!unknownType.isNull()) {
+ addr = CGM.getAddrOfUnknownAnyDecl(MD, unknownType);
} else {
- // Use an arbitrary non-function type to tell GetAddrOfFunction that the
- // function type is incomplete.
- Ty = ptrdiff_t;
+ 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);
}
- llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
- MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
+ MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t);
MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
}
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr 11 02:02:50 2011
@@ -4734,10 +4734,24 @@
if (result.isInvalid()) return ExprError();
args[i] = result.take();
- // Do l2r conversions on all the arguments.
- S.DefaultLvalueConversion(args[i]);
+ QualType argType;
- argTypes.push_back(args[i]->getType());
+ // 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
@@ -10145,6 +10159,10 @@
}
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
+ /// structure is not a goal.
struct RebuildUnknownAnyExpr
: StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
@@ -10157,64 +10175,19 @@
: S(S), DestType(castType) {}
ExprResult VisitStmt(Stmt *S) {
- llvm_unreachable("unexpected expression kind!");
+ llvm_unreachable("unexpected statement!");
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);
+ ExprResult VisitExpr(Expr *expr) {
+ S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+ << expr->getSourceRange();
+ return ExprError();
}
+ ExprResult VisitCallExpr(CallExpr *call);
+ ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message);
+
/// 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) {
@@ -10236,45 +10209,243 @@
return rebuildSugarExpr(op);
}
- 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);
+ ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice);
- // Rebuild the sub-expression as the pointee (function) type.
- DestType = DestType->castAs<PointerType>()->getPointeeType();
+ ExprResult resolveDecl(Expr *expr, NamedDecl *decl);
- ExprResult result = Visit(ice->getSubExpr());
- if (!result.isUsable()) return ExprError();
+ ExprResult VisitMemberExpr(MemberExpr *mem);
- ice->setSubExpr(result.take());
- return S.Owned(ice);
+ ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
+ return resolveDecl(ref, ref->getDecl());
}
+ };
+}
- ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
- ExprValueKind valueKind = VK_LValue;
- 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;
- }
+/// Rebuilds a call expression which yielded __unknown_anytype.
+ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) {
+ Expr *callee = call->getCallee();
+
+ enum FnKind {
+ FK_Function,
+ FK_FunctionPointer,
+ FK_BlockPointer
+ };
+
+ FnKind kind;
+ QualType type = callee->getType();
+ if (type->isFunctionType()) {
+ assert(isa<CXXMemberCallExpr>(call) || isa<CXXOperatorCallExpr>(call));
+ kind = FK_Function;
+ } else if (const PointerType *ptr = type->getAs<PointerType>()) {
+ type = ptr->getPointeeType();
+ kind = FK_FunctionPointer;
+ } else {
+ type = type->castAs<BlockPointerType>()->getPointeeType();
+ kind = FK_BlockPointer;
+ }
+ 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 (kind == FK_BlockPointer)
+ diagID = diag::err_block_returning_array_function;
- return S.Owned(ImplicitCastExpr::Create(S.Context, DestType,
- CK_ResolveUnknownAnyType,
- ref, 0, valueKind));
+ 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.
+ switch (kind) {
+ case FK_Function:
+ // Nothing to do.
+ break;
+
+ case FK_FunctionPointer:
+ DestType = S.Context.getPointerType(DestType);
+ break;
+
+ case FK_BlockPointer:
+ DestType = S.Context.getBlockPointerType(DestType);
+ break;
+ }
+
+ // 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);
+}
+
+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.
+
+ const ReferenceType *refTy = DestType->getAs<ReferenceType>();
+ if (refTy) {
+ // Hack 1: if we're returning a reference, make the message
+ // send return a pointer instead.
+ DestType = S.Context.getPointerType(refTy->getPointeeType());
+ }
+
+ // Change the type of the message.
+ msg->setType(DestType);
+ assert(msg->getValueKind() == VK_RValue);
+
+ // Hack 2: remove the method decl so that clients won't just
+ // ignore the expression's type. This is imperfect and can lead
+ // to expressions being completely lost.
+ msg->setSelector(msg->getMethodDecl()->getSelector());
+
+ // Hack 3: if we're returning a reference, dereference the
+ // pointer return.
+ Expr *result = msg;
+ if (refTy) {
+ SourceLocation loc;
+ result = new (S.Context) UnaryOperator(result, UO_Deref,
+ refTy->getPointeeType(),
+ VK_LValue, OK_Ordinary, loc);
+
+ // Hack 4: if we're returning an *rvalue* reference, cast to that.
+ if (isa<RValueReferenceType>(refTy)) {
+ TypeSourceInfo *tsi =
+ S.Context.getTrivialTypeSourceInfo(QualType(refTy, 0), loc);
+ result = CStyleCastExpr::Create(S.Context, refTy->getPointeeType(),
+ VK_XValue, CK_LValueBitCast,
+ result, 0, tsi, loc, loc);
}
- };
+ }
+
+ return S.MaybeBindToTemporary(result);
+}
+
+ExprResult RebuildUnknownAnyExpr::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);
+
+ // Rebuild the sub-expression as the pointee (function) type.
+ DestType = DestType->castAs<PointerType>()->getPointeeType();
+
+ ExprResult result = Visit(ice->getSubExpr());
+ if (!result.isUsable()) return ExprError();
+
+ ice->setSubExpr(result.take());
+ return S.Owned(ice);
+}
+
+ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *decl) {
+ ExprValueKind valueKind = VK_LValue;
+ CastKind castKind = CK_ResolveUnknownAnyType;
+ QualType type = DestType;
+
+ // We know how to make this work for certain kinds of decls:
+
+ // - functions
+ if (isa<FunctionDecl>(decl)) {
+ if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
+ if (method->isInstance()) valueKind = VK_RValue;
+
+ // This is true because FunctionDecls must always have function
+ // type, so we can't be resolving the entire thing at once.
+ assert(type->isFunctionType());
+
+ // Function references aren't l-values in C.
+ if (!S.getLangOptions().CPlusPlus)
+ valueKind = VK_RValue;
+
+ // - variables
+ } else if (isa<VarDecl>(decl)) {
+ if (S.getLangOptions().CPlusPlus) {
+ // If we're resolving to a reference type, the type of the
+ // expression is the pointee type, and we need to use a
+ // different cast kind so that we know to do the extra load.
+ if (const ReferenceType *refTy = type->getAs<ReferenceType>()) {
+ type = refTy->getPointeeType();
+ castKind = CK_ResolveUnknownAnyTypeToReference;
+ }
+ } else if (type->isFunctionType()) {
+ // Function references aren't l-values in C.
+ valueKind = VK_RValue;
+ }
+
+ // - nothing else
+ } else {
+ S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl)
+ << decl << expr->getSourceRange();
+ return ExprError();
+ }
+
+ return S.Owned(ImplicitCastExpr::Create(S.Context, type, castKind,
+ expr, 0, valueKind));
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitMemberExpr(MemberExpr *mem) {
+ NamedDecl *decl = mem->getMemberDecl();
+ CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl);
+ if (!method || !method->isInstance())
+ return resolveDecl(mem, decl);
+
+ // Rebuild instance-method references as applications of .* or ->*.
+ Expr *base = mem->getBase();
+
+ assert(DestType->isFunctionType());
+
+ // Make a decl ref.
+ TemplateArgumentListInfo explicitArgs;
+ mem->copyTemplateArgumentsInto(explicitArgs);
+ Expr *rhs = DeclRefExpr::Create(S.Context, mem->getQualifierLoc(),
+ method, mem->getMemberNameInfo(),
+ method->getType(), VK_RValue, &explicitArgs);
+
+ // Turn that into a member pointer constant.
+ const Type *recordTy =
+ S.Context.getTypeDeclType(method->getParent()).getTypePtr();
+ QualType mpt = S.Context.getMemberPointerType(method->getType(), recordTy);
+ rhs = new (S.Context) UnaryOperator(rhs, UO_AddrOf, mpt, VK_RValue,
+ OK_Ordinary, SourceLocation());
+
+ // Resolve that.
+ rhs = ImplicitCastExpr::Create(S.Context,
+ S.Context.getMemberPointerType(DestType, recordTy),
+ CK_ResolveUnknownAnyType, rhs, 0, VK_RValue);
+
+ // Turn that into a binary .* or ->*.
+ Expr *result = new (S.Context) BinaryOperator(base, rhs,
+ mem->isArrow() ? BO_PtrMemI : BO_PtrMemD,
+ DestType, VK_RValue,
+ OK_Ordinary, SourceLocation());
+
+ return S.Owned(result);
}
/// Check a cast of an unknown-any type. We intentionally only
@@ -10295,18 +10466,37 @@
static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) {
Expr *orig = e;
+ unsigned diagID = diag::err_uncasted_use_of_unknown_any;
while (true) {
e = e->IgnoreParenImpCasts();
- if (CallExpr *call = dyn_cast<CallExpr>(e))
+ if (CallExpr *call = dyn_cast<CallExpr>(e)) {
e = call->getCallee();
- else
+ diagID = diag::err_uncasted_call_of_unknown_any;
+ } else {
break;
+ }
+ }
+
+ SourceLocation loc;
+ NamedDecl *d;
+ if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
+ loc = ref->getLocation();
+ d = ref->getDecl();
+ } else if (MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
+ loc = mem->getMemberLoc();
+ d = mem->getMemberDecl();
+ } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(e)) {
+ diagID = diag::err_uncasted_call_of_unknown_any;
+ loc = msg->getSelectorLoc();
+ d = msg->getMethodDecl();
+ assert(d && "unknown method returning __unknown_any?");
+ } else {
+ S.Diag(e->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+ << e->getSourceRange();
+ return ExprError();
}
- 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();
+ S.Diag(loc, diagID) << d << orig->getSourceRange();
// Never recoverable.
return ExprError();
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Apr 11 02:02:50 2011
@@ -2177,6 +2177,7 @@
}
// Various C++ casts that are not handled yet.
case CK_ResolveUnknownAnyType:
+ case CK_ResolveUnknownAnyTypeToReference:
case CK_Dynamic:
case CK_ToUnion:
case CK_BaseToDerived:
Modified: cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/unknown-anytype.cpp Mon Apr 11 02:02:50 2011
@@ -55,3 +55,22 @@
// CHECK: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
return (Test7) test7_any(5);
}
+
+struct Test8 {
+ __unknown_anytype foo();
+ __unknown_anytype foo(int);
+
+ void test();
+};
+void Test8::test() {
+ (int) foo();
+ (int) foo(5);
+ (float) this->foo();
+ (float) this->foo(5);
+}
+void test8(Test8 *p) {
+ (double) p->foo();
+ (double) p->foo(5);
+ (bool) (*p).foo();
+ (bool) (*p).foo(5);
+}
Modified: cfe/trunk/test/SemaCXX/unknown-anytype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-anytype.cpp?rev=129269&r1=129268&r2=129269&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/SemaCXX/unknown-anytype.cpp Mon Apr 11 02:02:50 2011
@@ -15,7 +15,14 @@
// properly.
int x = foo; // expected-error {{cannot initialize}}
- int y = 0 + foo; // expected-error {{no known type for 'foo'; must explicitly cast this expression to use it}}
+ int y = 0 + foo; // expected-error {{'foo' has unknown type}}
return foo; // expected-error {{cannot initialize}}
}
}
+
+namespace test2 {
+ extern __unknown_anytype foo();
+ void test() {
+ foo(); // expected-error {{'foo' has unknown return type}}
+ }
+}
More information about the cfe-commits
mailing list