From: John McCall Date: Sun, 15 May 2011 17:49:20 +0000 (+0000) Subject: Add a method for checking whether a function is one of the reserved global X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=23c608d6815f188cb0bd3444c9708383c6461036;p=clang 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 --- 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(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(getDeclContext())) return false; + assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + const FunctionProtoType *proto = getType()->castAs(); + if (proto->getNumArgs() != 2 || proto->isVariadic()) return false; + + ASTContext &Context = + cast(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 {