diff options
-rw-r--r-- | include/clang/AST/Decl.h | 19 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 32 |
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 { |