CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
CanQualType VoidPtrTy, NullPtrTy;
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
+ CanQualType BuiltinFnTy;
CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
CanQualType ObjCBuiltinBoolTy;
// unknown type, most notably explicit casts.
PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy)
+PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
+
// The type of a cast which, in ARC, would normally require a
// __bridge, but which might be okay depending on the immediate
// context.
///
/// This particular cast kind is used for the conversion from a C++11
/// lambda expression to a block pointer.
- CK_CopyAndAutoreleaseBlockObject
+ CK_CopyAndAutoreleaseBlockObject,
+
+ // Convert a builtin function to a function pointer; only allowed in the
+ // callee of a call expression.
+ CK_BuiltinFnToFnPtr
};
static const CastKind CK_Invalid = static_cast<CastKind>(-1);
"%0 declared here">;
def note_defined_here : Note<"%0 defined here">;
+def err_builtin_fn_use : Error<"builtin functions must be directly called">;
+
def warn_call_wrong_number_of_arguments : Warning<
"too %select{few|many}0 arguments in call to %1">;
def err_atomic_builtin_must_be_pointer : Error<
/// \brief The pseudo-object placeholder type.
PREDEF_TYPE_PSEUDO_OBJECT = 35,
/// \brief The __va_list_tag placeholder type.
- PREDEF_TYPE_VA_LIST_TAG = 36
+ PREDEF_TYPE_VA_LIST_TAG = 36,
+ /// \brief The placeholder type for builtin functions.
+ PREDEF_TYPE_BUILTIN_FN = 37
};
/// \brief The number of predefined type IDs that are reserved for
// Placeholder type for unbridged ARC casts.
InitBuiltinType(ARCUnbridgedCastTy, BuiltinType::ARCUnbridgedCast);
+ // Placeholder type for builtin functions.
+ InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn);
+
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
assert(getType()->isBlockPointerType());
assert(getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
-
+
+ case CK_FunctionToPointerDecay:
+ assert(getType()->isPointerType());
+ assert(getSubExpr()->getType()->isFunctionType());
+ goto CheckNoBasePath;
+
// These should not have an inheritance path.
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
- case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
case CK_NullToPointer:
case CK_ConstructorConversion:
case CK_IntegralComplexToBoolean:
case CK_LValueBitCast: // -> bool&
case CK_UserDefinedConversion: // operator bool()
+ case CK_BuiltinFnToFnPtr:
CheckNoBasePath:
assert(path_empty() && "Cast kind should not have a base path!");
break;
return "NonAtomicToAtomic";
case CK_CopyAndAutoreleaseBlockObject:
return "CopyAndAutoreleaseBlockObject";
+ case CK_BuiltinFnToFnPtr:
+ return "BuiltinFnToFnPtr";
}
llvm_unreachable("Unhandled cast kind!");
case CK_IntegralRealToComplex:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
+ case CK_BuiltinFnToFnPtr:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
case BuiltinType::ARCUnbridgedCast:
case BuiltinType::Half:
case BuiltinType::PseudoObject:
+ case BuiltinType::BuiltinFn:
break;
}
case Dependent: return "<dependent type>";
case UnknownAny: return "<unknown type>";
case ARCUnbridgedCast: return "<ARC unbridged cast type>";
+ case BuiltinFn: return "<builtin fn type>";
case ObjCId: return "id";
case ObjCClass: return "Class";
case ObjCSel: return "SEL";
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
+ case BuiltinType::BuiltinFn:
return TST_unspecified;
}
case CK_Dependent:
llvm_unreachable("dependent cast kind in IR gen!");
-
+
+ case CK_BuiltinFnToFnPtr:
+ llvm_unreachable("builtin functions are handled elsewhere");
+
// These two casts are currently treated as no-ops, although they could
// potentially be real operations depending on the target's ABI.
case CK_NonAtomicToAtomic:
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
llvm_unreachable("cast kind invalid for aggregate types");
}
}
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
case CK_Dependent: llvm_unreachable("saw dependent cast!");
+ case CK_BuiltinFnToFnPtr:
+ llvm_unreachable("builtin functions are handled elsewhere");
+
case CK_ReinterpretMemberPointer:
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerivedMemberPointer:
// are in the same order as in the CastKind enum.
switch (Kind) {
case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
-
+ case CK_BuiltinFnToFnPtr:
+ llvm_unreachable("builtin functions are handled elsewhere");
+
case CK_LValueBitCast:
case CK_ObjCObjectLValueCast: {
Value *V = EmitLValue(E).getAddress();
case CK_ARCExtendBlockObject:
case CK_NonAtomicToAtomic:
case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
return false;
}
}
NewBuiltinDecl,
/*enclosing*/ false,
DRE->getLocation(),
- NewBuiltinDecl->getType(),
+ Context.BuiltinFnTy,
DRE->getValueKind());
// Set the callee in the CallExpr.
- // FIXME: This leaks the original parens and implicit casts.
- ExprResult PromotedCall = UsualUnaryConversions(NewDRE);
- if (PromotedCall.isInvalid())
- return ExprError();
+ // FIXME: This loses syntactic information.
+ QualType CalleePtrTy = Context.getPointerType(NewBuiltinDecl->getType());
+ ExprResult PromotedCall = ImpCastExprToType(NewDRE, CalleePtrTy,
+ CK_BuiltinFnToFnPtr);
TheCall->setCallee(PromotedCall.take());
// Change the result type of the call to match the original value type. This
}
CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
- CollectableMemCpy->getType(),
- VK_LValue, Loc, 0).take();
+ Context.BuiltinFnTy,
+ VK_RValue, Loc, 0).take();
assert(CollectableMemCpyRef && "Builtin reference cannot fail");
}
}
}
BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy,
- BuiltinMemCpy->getType(),
- VK_LValue, Loc, 0).take();
+ Context.BuiltinFnTy,
+ VK_RValue, Loc, 0).take();
assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
}
}
CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
- CollectableMemCpy->getType(),
- VK_LValue, Loc, 0).take();
+ Context.BuiltinFnTy,
+ VK_RValue, Loc, 0).take();
assert(CollectableMemCpyRef && "Builtin reference cannot fail");
}
}
}
BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy,
- BuiltinMemCpy->getType(),
- VK_LValue, Loc, 0).take();
+ Context.BuiltinFnTy,
+ VK_RValue, Loc, 0).take();
assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
}
}
case Decl::Function: {
+ if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
+ if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
+ type = Context.BuiltinFnTy;
+ valueKind = VK_RValue;
+ break;
+ }
+ }
+
const FunctionType *fty = type->castAs<FunctionType>();
// If we're referring to a function with an __unknown_anytype
SourceLocation RParenLoc,
Expr *Config, bool IsExecConfig) {
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
+ unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
// Promote the function operand.
- ExprResult Result = UsualUnaryConversions(Fn);
+ // We special-case function promotion here because we only allow promoting
+ // builtin functions to function pointers in the callee of a call.
+ ExprResult Result;
+ if (BuiltinID &&
+ Fn->getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)) {
+ Result = ImpCastExprToType(Fn, Context.getPointerType(FDecl->getType()),
+ CK_BuiltinFnToFnPtr).take();
+ } else {
+ Result = UsualUnaryConversions(Fn);
+ }
if (Result.isInvalid())
return ExprError();
Fn = Result.take();
VK_RValue,
RParenLoc);
- unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
-
// Bail out early if calling a builtin with custom typechecking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
break;
case UO_Deref: {
Input = DefaultFunctionArrayLvalueConversion(Input.take());
+ if (Input.isInvalid()) return ExprError();
resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
break;
}
case BuiltinType::PseudoObject:
return checkPseudoObjectRValue(E);
+ case BuiltinType::BuiltinFn:
+ Diag(E->getLocStart(), diag::err_builtin_fn_use);
+ return ExprError();
+
// Everything else should be impossible.
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id:
// Build a reference to the __builtin_shufflevector builtin
FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
- ExprResult Callee
- = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, false,
- Builtin->getType(),
- VK_LValue, BuiltinLoc));
- Callee = SemaRef.UsualUnaryConversions(Callee.take());
- if (Callee.isInvalid())
- return ExprError();
+ Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, false,
+ SemaRef.Context.BuiltinFnTy,
+ VK_RValue, BuiltinLoc);
+ QualType CalleePtrTy = SemaRef.Context.getPointerType(Builtin->getType());
+ Callee = SemaRef.ImpCastExprToType(Callee, CalleePtrTy,
+ CK_BuiltinFnToFnPtr).take();
// Build the CallExpr
ExprResult TheCall = SemaRef.Owned(
- new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(), SubExprs,
+ new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, SubExprs,
Builtin->getCallResultType(),
Expr::getValueKindForType(Builtin->getResultType()),
RParenLoc));
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;
+ case BuiltinType::BuiltinFn:
+ ID = PREDEF_TYPE_BUILTIN_FN; break;
+
}
return TypeIdx(ID);
case PREDEF_TYPE_VA_LIST_TAG:
T = Context.getVaListTagType();
break;
+
+ case PREDEF_TYPE_BUILTIN_FN:
+ T = Context.BuiltinFnTy;
+ break;
}
assert(!T.isNull() && "Unknown predefined type");
case CK_NoOp:
case CK_ConstructorConversion:
case CK_UserDefinedConversion:
- case CK_FunctionToPointerDecay: {
+ case CK_FunctionToPointerDecay:
+ case CK_BuiltinFnToFnPtr: {
// Copy the SVal of Ex to CastE.
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
// CHECK: call signext i8 @memmove()
return memmove();
}
-
-// <rdar://problem/10063539>
-
-template<int (*Compare)(const char *s1, const char *s2)>
-int equal(const char *s1, const char *s2) {
- return Compare(s1, s2) == 0;
-}
-
-// CHECK: define weak_odr i32 @_Z5equalIXadL_Z16__builtin_strcmpPKcS1_EEEiS1_S1_
-// CHECK: call i32 @strcmp
-template int equal<&__builtin_strcmp>(const char*, const char*);
-
static int ary[__builtin_classify_type(a)];
static int ary2[(__builtin_classify_type)(a)]; // expected-error{{variable length array declaration can not have 'static' storage duration}}
- static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{variable length array declaration can not have 'static' storage duration}}
+ static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{builtin functions must be directly called}}
int result;
}
void a() { __builtin_va_list x, y; ::__builtin_va_copy(x, y); }
+
+// <rdar://problem/10063539>
+template<int (*Compare)(const char *s1, const char *s2)>
+int equal(const char *s1, const char *s2) {
+ return Compare(s1, s2) == 0;
+}
+// FIXME: Our error recovery here sucks
+template int equal<&__builtin_strcmp>(const char*, const char*); // expected-error {{builtin functions must be directly called}} expected-error {{expected unqualified-id}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+
+// PR13195
+void f2() {
+ __builtin_isnan; // expected-error {{builtin functions must be directly called}}
+}