aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-05-15 17:49:20 +0000
committerJohn McCall <rjmccall@apple.com>2011-05-15 17:49:20 +0000
commit23c608d6815f188cb0bd3444c9708383c6461036 (patch)
tree8d1d545ac3f525f3423b0086395a8f517e4ebdf3
parentadf5dc340db3ea99de5fe3f6c42cfee1807d445e (diff)
Add a method for checking whether a function is one of the reserved global
placement allocation or deallocation functions. These functions cannot be replaced by the user and are exempt from the normal requirements on allocation functions (e.g. that they must return unaliased memory). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131386 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h19
-rw-r--r--lib/AST/Decl.cpp32
2 files changed, 45 insertions, 6 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 6ca14ce874..e1dad644c9 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1644,10 +1644,25 @@ public:
bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
void setDeletedAsWritten(bool D = true) { IsDeleted = D; }
- /// \brief Determines whether this is a function "main", which is
- /// the entry point into an executable program.
+ /// \brief Determines whether this function is "main", which is the
+ /// entry point into an executable program.
bool isMain() const;
+ /// \brief Determines whether this operator new or delete is one
+ /// of the reserved global placement operators:
+ /// void *operator new(size_t, void *);
+ /// void *operator new[](size_t, void *);
+ /// void operator delete(void *, void *);
+ /// void operator delete[](void *, void *);
+ /// These functions have special behavior under [new.delete.placement]:
+ /// These functions are reserved, a C++ program may not define
+ /// functions that displace the versions in the Standard C++ library.
+ /// The provisions of [basic.stc.dynamic] do not apply to these
+ /// reserved placement forms of operator new and operator delete.
+ ///
+ /// This function must be an allocation or deallocation function.
+ bool isReservedGlobalPlacementOperator() const;
+
/// \brief Determines whether this function is a function with
/// external, C linkage.
bool isExternC() const;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d4df017383..1e98998002 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1475,10 +1475,34 @@ void FunctionDecl::setPure(bool P) {
}
bool FunctionDecl::isMain() const {
- ASTContext &Context = getASTContext();
- return !Context.getLangOptions().Freestanding &&
- getDeclContext()->getRedeclContext()->isTranslationUnit() &&
- getIdentifier() && getIdentifier()->isStr("main");
+ const TranslationUnitDecl *tunit =
+ dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
+ return tunit &&
+ tunit->getASTContext().getLangOptions().Freestanding &&
+ getIdentifier() &&
+ getIdentifier()->isStr("main");
+}
+
+bool FunctionDecl::isReservedGlobalPlacementOperator() const {
+ assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName);
+ assert(getDeclName().getCXXOverloadedOperator() == OO_New ||
+ getDeclName().getCXXOverloadedOperator() == OO_Delete ||
+ getDeclName().getCXXOverloadedOperator() == OO_Array_New ||
+ getDeclName().getCXXOverloadedOperator() == OO_Array_Delete);
+
+ if (isa<CXXRecordDecl>(getDeclContext())) return false;
+ assert(getDeclContext()->getRedeclContext()->isTranslationUnit());
+
+ const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>();
+ if (proto->getNumArgs() != 2 || proto->isVariadic()) return false;
+
+ ASTContext &Context =
+ cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext())
+ ->getASTContext();
+
+ // The result type and first argument type are constant across all
+ // these operators. The second argument must be exactly void*.
+ return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy);
}
bool FunctionDecl::isExternC() const {