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;
}
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 {