summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/docs/LanguageExtensions.rst18
-rw-r--r--clang/include/clang/Basic/Builtins.def4
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td1
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp6
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp17
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h6
-rw-r--r--clang/lib/Sema/SemaChecking.cpp16
-rw-r--r--clang/test/CodeGenCXX/new.cpp9
-rw-r--r--clang/test/Sema/builtins.c5
9 files changed, 79 insertions, 3 deletions
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 4e38a16ba14..2de18ce885b 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1446,6 +1446,24 @@ object that overloads ``operator&``.
return __builtin_addressof(value);
}
+``__builtin_operator_new`` and ``__builtin_operator_delete``
+------------------------------------------------------------
+
+``__builtin_operator_new`` allocates memory just like a non-placement non-class
+*new-expression*. This is exactly like directly calling the normal
+non-placement ``::operator new``, except that it allows certain optimizations
+that the C++ standard does not permit for a direct function call to
+``::operator new`` (in particular, removing ``new`` / ``delete`` pairs and
+merging allocations).
+
+Likewise, ``__builtin_operator_delete`` deallocates memory just like a
+non-class *delete-expression*, and is exactly like directly calling the normal
+``::operator delete``, except that it permits optimizations. Only the unsized
+form of ``__builtin_operator_delete`` is currently available.
+
+These builtins are intended for use in the implementation of ``std::allocator``
+and other similar allocation libraries, and are only available in C++.
+
Multiprecision Arithmetic Builtins
----------------------------------
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 3a1c58f4317..4c356f1c75d 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -73,7 +73,7 @@
// be followed by ':headername:' to state which header this function
// comes from.
// i -> this is a runtime library implemented function without the
-// '__builtin_' prefix. It will be implemented in compiter-rt or libgcc.
+// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc.
// p:N: -> this is a printf-like function whose Nth argument is the format
// string.
// P:N: -> similar to the p:N: attribute, but the function is like vprintf
@@ -1204,6 +1204,8 @@ BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
// Clang builtins (not available in GCC).
BUILTIN(__builtin_addressof, "v*v&", "nct")
+BUILTIN(__builtin_operator_new, "v*z", "c")
+BUILTIN(__builtin_operator_delete, "vv*", "n")
#undef BUILTIN
#undef LIBBUILTIN
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9c648e88a93..28273caa6ce 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6682,6 +6682,7 @@ def err_argument_invalid_range : Error<
def err_builtin_longjmp_invalid_val : Error<
"argument to __builtin_longjmp must be a constant 1">;
+def err_builtin_requires_language : Error<"'%0' is only available in %1">;
def err_constant_integer_arg_type : Error<
"argument to %0 must be a constant integer">;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8b62ef0ceda..f705ed80c14 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1508,6 +1508,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin_addressof:
return RValue::get(EmitLValue(E->getArg(0)).getAddress());
+ case Builtin::BI__builtin_operator_new:
+ return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
+ E->getArg(0), false);
+ case Builtin::BI__builtin_operator_delete:
+ return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
+ E->getArg(0), true);
case Builtin::BI__noop:
return RValue::get(nullptr);
case Builtin::BI_InterlockedCompareExchange: {
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 762d8e29595..0492813f8fa 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1029,6 +1029,23 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
return RV;
}
+RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
+ const Expr *Arg,
+ bool IsDelete) {
+ CallArgList Args;
+ const Stmt *ArgS = Arg;
+ EmitCallArgs(Args, *Type->param_type_begin(),
+ ConstExprIterator(&ArgS), ConstExprIterator(&ArgS + 1));
+ // Find the allocation or deallocation function that we're calling.
+ ASTContext &Ctx = getContext();
+ DeclarationName Name = Ctx.DeclarationNames
+ .getCXXOperatorName(IsDelete ? OO_Delete : OO_New);
+ for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name))
+ if (Ctx.hasSameType(cast<FunctionDecl>(Decl)->getType(), QualType(Type, 0)))
+ return EmitNewDeleteCall(*this, cast<FunctionDecl>(Decl), Type, Args);
+ llvm_unreachable("predeclared global operator new/delete is missing");
+}
+
namespace {
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression.
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index d1e63a710bc..b6c58e0ee16 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1659,6 +1659,9 @@ public:
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,
QualType DeleteTy);
+ RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
+ const Expr *Arg, bool IsDelete);
+
llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
llvm::Value* EmitCXXUuidofExpr(const CXXUuidofExpr *E);
@@ -2641,7 +2644,8 @@ public:
void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd, bool ForceColumnInfo);
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ForceColumnInfo = false);
private:
const TargetCodeGenInfo &getTargetHooks() const {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 60514efd55c..916ce7d9855 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -296,8 +296,22 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinAddressof(*this, TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_operator_new:
+ case Builtin::BI__builtin_operator_delete:
+ if (!getLangOpts().CPlusPlus) {
+ Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language)
+ << (BuiltinID == Builtin::BI__builtin_operator_new
+ ? "__builtin_operator_new"
+ : "__builtin_operator_delete")
+ << "C++";
+ return ExprError();
+ }
+ // CodeGen assumes it can find the global new and delete to call,
+ // so ensure that they are declared.
+ DeclareGlobalNewDelete();
+ break;
}
-
+
// Since the target specific builtins for each arch overlap, only check those
// of the arch we are compiling for.
if (BuiltinID >= Builtin::FirstTSBuiltin) {
diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp
index 26db84225f1..d8aa258cbbf 100644
--- a/clang/test/CodeGenCXX/new.cpp
+++ b/clang/test/CodeGenCXX/new.cpp
@@ -326,6 +326,15 @@ namespace N3664 {
}
}
+namespace builtins {
+ // CHECK-LABEL: define void @_ZN8builtins1fEv
+ void f() {
+ // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]]
+ // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
+ __builtin_operator_delete(__builtin_operator_new(4));
+ }
+}
+
// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}}
// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c
index 8ca33c8e752..7647100bc27 100644
--- a/clang/test/Sema/builtins.c
+++ b/clang/test/Sema/builtins.c
@@ -197,3 +197,8 @@ void no_ms_builtins() {
__noop(1); // expected-warning {{implicit declaration}}
__debugbreak(); // expected-warning {{implicit declaration}}
}
+
+void unavailable() {
+ __builtin_operator_new(0); // expected-error {{'__builtin_operator_new' is only available in C++}}
+ __builtin_operator_delete(0); // expected-error {{'__builtin_operator_delete' is only available in C++}}
+}
OpenPOWER on IntegriCloud