aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-08-31 00:14:07 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-08-31 00:14:07 +0000
commita6c66cedc022c9e5d45a937d6b8cff491a6bf81b (patch)
tree22786c2c1573674a6e48ac4e7b0af5d7ad453d9a /lib/Sema
parent918546c584c91ee917c919c967d7d73cecd295dc (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.cpp10
-rw-r--r--lib/Sema/SemaDeclCXX.cpp16
-rw-r--r--lib/Sema/SemaExpr.cpp27
-rw-r--r--lib/Sema/TreeTransform.h15
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));