diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-08-31 00:14:07 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-08-31 00:14:07 +0000 |
commit | a6c66cedc022c9e5d45a937d6b8cff491a6bf81b (patch) | |
tree | 22786c2c1573674a6e48ac4e7b0af5d7ad453d9a /lib/Sema | |
parent | 918546c584c91ee917c919c967d7d73cecd295dc (diff) |
Change the representation of builtin functions in the AST
(__builtin_* etc.) so that it isn't possible to take their address.
Specifically, introduce a new type to represent a reference to a builtin
function, and a new cast kind to convert it to a function pointer in the
operand of a call. Fixes PR13195.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162962 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 27 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 15 |
4 files changed, 44 insertions, 24 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 8760c5e77f..137f3e1a5e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1232,14 +1232,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { 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 diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9fbe14a16c..176e3fecb9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7847,8 +7847,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, - CollectableMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(CollectableMemCpyRef && "Builtin reference cannot fail"); } } @@ -7867,8 +7867,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, - BuiltinMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); } @@ -8396,8 +8396,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, - CollectableMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(CollectableMemCpyRef && "Builtin reference cannot fail"); } } @@ -8416,8 +8416,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, - BuiltinMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f2e6070539..57dab09e46 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2416,6 +2416,14 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } 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 @@ -3929,9 +3937,19 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, 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(); @@ -3953,8 +3971,6 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, 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); @@ -8635,6 +8651,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, break; case UO_Deref: { Input = DefaultFunctionArrayLvalueConversion(Input.take()); + if (Input.isInvalid()) return ExprError(); resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); break; } @@ -11747,6 +11764,10 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { 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: diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 2bbc41326e..19636f4143 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2413,17 +2413,16 @@ public: // 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)); |