https://github.com/MaxEW707 updated https://github.com/llvm/llvm-project/pull/72209
>From 75cf305fe732d00be910a6aa0afe79953c5b7186 Mon Sep 17 00:00:00 2001 From: MaxEW707 <82551778+maxew...@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:36:58 -0500 Subject: [PATCH 1/3] Implement `::_placement_new` expression for built-in global placement new without header includes, overload resolution or dealing with std libraries that declare the global placement new with attributes that cannot be redeclared. --- clang/include/clang/AST/ExprCXX.h | 23 +++++++++ clang/include/clang/AST/Stmt.h | 4 ++ .../clang/Basic/DiagnosticParseKinds.td | 2 + clang/include/clang/Basic/TokenKinds.def | 1 + clang/include/clang/Sema/Sema.h | 4 +- clang/lib/AST/ASTImporter.cpp | 18 ++++--- clang/lib/AST/ExprCXX.cpp | 34 +++++++++++++ clang/lib/AST/ExprConstant.cpp | 7 ++- clang/lib/AST/JSONNodeDumper.cpp | 1 + clang/lib/AST/StmtPrinter.cpp | 5 +- clang/lib/AST/StmtProfile.cpp | 1 + clang/lib/AST/TextNodeDumper.cpp | 2 + clang/lib/CodeGen/CGExprCXX.cpp | 8 ++-- clang/lib/CodeGen/CodeGenModule.cpp | 5 +- clang/lib/Interpreter/Interpreter.cpp | 4 +- clang/lib/Parse/ParseDecl.cpp | 6 ++- clang/lib/Parse/ParseExpr.cpp | 2 +- clang/lib/Parse/ParseExprCXX.cpp | 19 ++++++-- clang/lib/Parse/ParseObjc.cpp | 1 + clang/lib/Parse/ParseTentative.cpp | 3 +- clang/lib/Sema/SemaExprCXX.cpp | 48 ++++++++++++++----- clang/lib/Sema/TreeTransform.h | 6 +-- clang/lib/Serialization/ASTReaderStmt.cpp | 2 + clang/lib/Serialization/ASTWriterStmt.cpp | 2 + .../Checkers/CheckPlacementNew.cpp | 2 +- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 9 ++-- clang/test/AST/ast-dump-expr.cpp | 14 ++++++ clang/test/CodeGenCXX/new.cpp | 44 ++++++++++++++++- clang/test/SemaCXX/new-delete.cpp | 7 +++ 29 files changed, 234 insertions(+), 50 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 24278016431837b..d760af796aea28f 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2282,6 +2282,13 @@ class CXXNewExpr final QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); + /// Build a c++ builtin placement new expression + CXXNewExpr(Expr *PlacementArg, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + /// Build an empty c++ new expression. CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, bool IsParenTypeId); @@ -2297,6 +2304,14 @@ class CXXNewExpr final QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); + /// Create a c++ builtin placement new expression. + static CXXNewExpr * + CreatePlacementNew(const ASTContext &Ctx, Expr *PlacementArg, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + /// Create an empty c++ new expression. static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray, bool HasInit, unsigned NumPlacementArgs, @@ -2332,6 +2347,12 @@ class CXXNewExpr final FunctionDecl *getOperatorDelete() const { return OperatorDelete; } void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } + bool isReservedPlacementNew() const { + if (CXXNewExprBits.IsPlacementNewExpr) + return true; + return OperatorNew->isReservedGlobalPlacementOperator(); + } + bool isArray() const { return CXXNewExprBits.IsArray; } /// This might return std::nullopt even if isArray() returns true, @@ -2387,6 +2408,8 @@ class CXXNewExpr final bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } + bool isPlacementNewExpr() const { return CXXNewExprBits.IsPlacementNewExpr; } + /// Whether this new-expression has any initializer at all. bool hasInitializer() const { switch (getInitializationStyle()) { diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index da7b37ce0e1211f..2dc3746aee4fd71 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -878,6 +878,10 @@ class alignas(void *) Stmt { LLVM_PREFERRED_TYPE(bool) unsigned IsParenTypeId : 1; + /// True is this if the builtin placement-new expression. + LLVM_PREFERRED_TYPE(bool) + unsigned IsPlacementNewExpr : 1; + /// The number of placement new arguments. unsigned NumPlacementArgs; }; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index de180344fcc5c74..c0ca7529fda892d 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -255,6 +255,8 @@ def err_expected_lbrace_in_compound_literal : Error< "expected '{' in compound literal">; def err_expected_while : Error<"expected 'while' in do/while loop">; +def err_placement_new_expected_one_argument : Error<"expected only one argument in placement params">; + def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">; def err_expected_semi_after_expr : Error<"expected ';' after expression">; def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 3ce317d318f9bb6..a2dfc1a9e08691a 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -365,6 +365,7 @@ KEYWORD(typeid , KEYCXX) KEYWORD(using , KEYCXX) KEYWORD(virtual , KEYCXX) KEYWORD(wchar_t , WCHARSUPPORT) +KEYWORD(_placement_new , KEYCXX) // C++ 2.5p2: Alternative Representations. CXX_KEYWORD_OPERATOR(and , ampamp) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f69f366c1750918..ab9a0d0713435b6 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6810,14 +6810,14 @@ class Sema final { bool ListInitialization); /// ActOnCXXNew - Parsed a C++ 'new' expression. - ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, Expr *Initializer); ExprResult - BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, + BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacementNewExpr, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, QualType AllocType, TypeSourceInfo *AllocTypeInfo, std::optional<Expr *> ArraySize, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c4e931e220f69b5..3204fb69b3440f7 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8102,12 +8102,18 @@ ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { ImportContainerChecked(E->placement_arguments(), ToPlacementArgs)) return std::move(Err); - return CXXNewExpr::Create( - Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, - ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(), - ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), - ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, - ToDirectInitRange); + if (E->isPlacementNewExpr()) + return CXXNewExpr::CreatePlacementNew( + Importer.getToContext(), ToPlacementArgs[0], ToTypeIdParens, ToArraySize, + E->getInitializationStyle(), ToInitializer, ToType, ToAllocatedTypeSourceInfo, + ToSourceRange, ToDirectInitRange); + else + return CXXNewExpr::Create( + Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, + ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(), + ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), + ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, + ToDirectInitRange); } ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 83af7998f683382..7c7f4c2f31542b9 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -207,6 +207,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, bool IsParenTypeId = TypeIdParens.isValid(); CXXNewExprBits.IsParenTypeId = IsParenTypeId; CXXNewExprBits.NumPlacementArgs = PlacementArgs.size(); + CXXNewExprBits.IsPlacementNewExpr = false; if (ArraySize) getTrailingObjects<Stmt *>()[arraySizeOffset()] = *ArraySize; @@ -234,6 +235,18 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, setDependence(computeDependence(this)); } +CXXNewExpr::CXXNewExpr(Expr *PlacementArg, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange) + : CXXNewExpr(true, nullptr, nullptr, false, false, + ArrayRef<Expr *>(&PlacementArg, 1), TypeIdParens, ArraySize, + InitializationStyle, Initializer, Ty, + AllocatedTypeInfo, Range, DirectInitRange) { + CXXNewExprBits.IsPlacementNewExpr = true; +} + CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, bool IsParenTypeId) : Expr(CXXNewExprClass, Empty) { @@ -265,6 +278,25 @@ CXXNewExpr *CXXNewExpr::Create( AllocatedTypeInfo, Range, DirectInitRange); } +CXXNewExpr *CXXNewExpr::CreatePlacementNew( + const ASTContext &Ctx, Expr *PlacementArg, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange) { + bool IsArray = ArraySize.has_value(); + bool HasInit = Initializer != nullptr; + bool IsParenTypeId = TypeIdParens.isValid(); + void *Mem = + Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>( + IsArray + HasInit + 1, IsParenTypeId), + alignof(CXXNewExpr)); + return new (Mem) + CXXNewExpr(PlacementArg, TypeIdParens, + ArraySize, InitializationStyle, Initializer, Ty, + AllocatedTypeInfo, Range, DirectInitRange); +} + CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray, bool HasInit, unsigned NumPlacementArgs, bool IsParenTypeId) { @@ -277,6 +309,8 @@ CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray, } bool CXXNewExpr::shouldNullCheckAllocation() const { + if (isPlacementNewExpr()) + return false; if (getOperatorNew()->getLangOpts().CheckNew) return true; return !getOperatorNew()->hasAttr<ReturnsNonNullAttr>() && diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index e16fec6109e744e..7652e22a6a51b4f 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9740,7 +9740,7 @@ static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This, QualType AllocType); bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { - if (!Info.getLangOpts().CPlusPlus20) + if (!Info.getLangOpts().CPlusPlus20 && !E->isPlacementNewExpr()) Info.CCEDiag(E, diag::note_constexpr_new); // We cannot speculatively evaluate a delete expression. @@ -9751,8 +9751,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { bool IsNothrow = false; bool IsPlacement = false; - if (OperatorNew->isReservedGlobalPlacementOperator() && - Info.CurrentCall->isStdFunction() && !E->isArray()) { + if (E->isReservedPlacementNew() && Info.CurrentCall->isStdFunction() && !E->isArray()) { // FIXME Support array placement new. assert(E->getNumPlacementArgs() == 1); if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) @@ -9760,7 +9759,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { if (Result.Designator.Invalid) return false; IsPlacement = true; - } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) { + } else if (E->isPlacementNewExpr() || !OperatorNew->isReplaceableGlobalAllocationFunction()) { Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) << isa<CXXMethodDecl>(OperatorNew) << OperatorNew; return false; diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index ace5178bf625828..82c4f5e64416e21 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1350,6 +1350,7 @@ void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); attributeOnlyIfTrue("isArray", NE->isArray()); attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); + attributeOnlyIfTrue("isPlacementNewExpr", NE->isPlacementNewExpr()); switch (NE->getInitializationStyle()) { case CXXNewInitializationStyle::None: case CXXNewInitializationStyle::Implicit: diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index ab4a013de5f552c..ce3d9b64de76ab0 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2271,7 +2271,10 @@ void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isGlobalNew()) OS << "::"; - OS << "new "; + if (E->isPlacementNewExpr()) + OS << "_placement_new "; + else + OS << "new "; unsigned NumPlace = E->getNumPlacementArgs(); if (NumPlace > 0 && !isa<CXXDefaultArgExpr>(E->getPlacementArg(0))) { OS << "("; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8128219dd6f63c9..c3590f50eebfd2e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2096,6 +2096,7 @@ void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) { ID.AddInteger(S->getNumPlacementArgs()); ID.AddBoolean(S->isGlobalNew()); ID.AddBoolean(S->isParenTypeId()); + ID.AddBoolean(S->isPlacementNewExpr()); ID.AddInteger(llvm::to_underlying(S->getInitializationStyle())); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e8274fcd5cfe9cb..57b6b9087826355 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1356,6 +1356,8 @@ void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) { OS << " global"; if (Node->isArray()) OS << " array"; + if (Node->isPlacementNewExpr()) + OS << " builtin placement-new expression"; if (Node->getOperatorNew()) { OS << ' '; dumpBareDeclRef(Node->getOperatorNew()); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 98ae56e2df88184..cfc16f2ffd3ad04 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -693,7 +693,7 @@ static CharUnits CalculateCookiePadding(CodeGenFunction &CGF, // No cookie is required if the operator new[] being used is the // reserved placement operator new[]. - if (E->getOperatorNew()->isReservedGlobalPlacementOperator()) + if (E->isReservedPlacementNew()) return CharUnits::Zero(); return CGF.CGM.getCXXABI().GetArrayCookieSize(E); @@ -1584,7 +1584,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // operator, just "inline" it directly. Address allocation = Address::invalid(); CallArgList allocatorArgs; - if (allocator->isReservedGlobalPlacementOperator()) { + if (E->isReservedPlacementNew()) { assert(E->getNumPlacementArgs() == 1); const Expr *arg = *E->placement_arguments().begin(); @@ -1599,6 +1599,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // Set up allocatorArgs for the call to operator delete if it's not // the reserved global operator. + assert(!E->isPlacementNewExpr() || !E->getOperatorDelete()); if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); @@ -1724,8 +1725,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // vptrs information which may be included in previous type. // To not break LTO with different optimizations levels, we do it regardless // of optimization level. - if (CGM.getCodeGenOpts().StrictVTablePointers && - allocator->isReservedGlobalPlacementOperator()) + if (CGM.getCodeGenOpts().StrictVTablePointers && E->isReservedPlacementNew()) result = Builder.CreateLaunderInvariantGroup(result); // Emit sanitizer checks for pointer value now, so that in the case of an diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4c7f516e308ca00..d0ed0289bcce52a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3837,7 +3837,10 @@ namespace { } bool VisitCXXNewExpr(CXXNewExpr *E) { - SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>(); + if (E->isPlacementNewExpr()) + SafeToInline = true; + else + SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>(); return SafeToInline; } }; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 7968c62cbd3e7b3..93ba4a060342a22 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -606,8 +606,8 @@ class RuntimeInterfaceBuilder Expr *Args[] = {AllocCall.get()}; ExprResult CXXNewCall = S.BuildCXXNew( E->getSourceRange(), - /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, - /*PlacementRParen=*/SourceLocation(), + /*UseGlobal=*/true, /*IsPlacementNewExpr=*/false, + /*PlacementLParen=*/SourceLocation(), Args, /*PlacementRParen=*/SourceLocation(), /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, E->getSourceRange(), E); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 78c3ab72979a007..18b2fd86e566e5c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5457,7 +5457,8 @@ bool Parser::isTypeSpecifierQualifier() { case tok::coloncolon: // ::foo::bar if (NextToken().is(tok::kw_new) || // ::new - NextToken().is(tok::kw_delete)) // ::delete + NextToken().is(tok::kw_delete) || // ::delete + NextToken().is(tok::kw__placement_new)) // ::_placement_new return false; if (TryAnnotateTypeOrScopeToken()) @@ -5650,7 +5651,8 @@ bool Parser::isDeclarationSpecifier( if (!getLangOpts().CPlusPlus) return false; if (NextToken().is(tok::kw_new) || // ::new - NextToken().is(tok::kw_delete)) // ::delete + NextToken().is(tok::kw_delete) || // ::delete + NextToken().is(tok::kw__placement_new)) // ::_placement_new return false; // Annotate typenames and C++ scope specifiers. If we get one, just diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 53fba3b2f59242b..9b2e03221d5d407 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1682,7 +1682,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // ::new -> [C++] new-expression // ::delete -> [C++] delete-expression SourceLocation CCLoc = ConsumeToken(); - if (Tok.is(tok::kw_new)) { + if (Tok.is(tok::kw_new) || Tok.is(tok::kw__placement_new)) { if (NotPrimaryExpression) *NotPrimaryExpression = true; Res = ParseCXXNewExpression(true, CCLoc); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 99b4931004546c1..f21680834cfc531 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -186,7 +186,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier( if (Tok.is(tok::coloncolon)) { // ::new and ::delete aren't nested-name-specifiers. tok::TokenKind NextKind = NextToken().getKind(); - if (NextKind == tok::kw_new || NextKind == tok::kw_delete) + if (NextKind == tok::kw_new || NextKind == tok::kw_delete || NextKind == tok::kw__placement_new) return false; if (NextKind == tok::l_brace) { @@ -3171,7 +3171,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, /// ExprResult Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { - assert(Tok.is(tok::kw_new) && "expected 'new' token"); + assert((Tok.is(tok::kw_new) || Tok.is(tok::kw__placement_new)) && "expected 'new' token"); + const bool IsPlacementNewExpr = Tok.is(tok::kw__placement_new); ConsumeToken(); // Consume 'new' // A '(' now can be a new-placement or the '(' wrapping the type-id in the @@ -3201,6 +3202,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return ExprError(); } + if (IsPlacementNewExpr) { + if (PlacementArgs.size() != 1) { + Diag(PlacementLParen, diag::err_placement_new_expected_one_argument); + SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); + return ExprError(); + } + } + if (PlacementArgs.empty()) { // Reset the placement locations. There was no placement. TypeIdParens = T.getRange(); @@ -3227,6 +3236,10 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { } } } + } else if (IsPlacementNewExpr) { + Diag(Tok, diag::err_expected_lparen_after) << "::_placement_new"; + SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); + return ExprError(); } else { // A new-type-id is a simplified type-id, where essentially the // direct-declarator is replaced by a direct-new-declarator. @@ -3295,7 +3308,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { if (Initializer.isInvalid()) return Initializer; - return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, + return Actions.ActOnCXXNew(Start, UseGlobal, IsPlacementNewExpr, PlacementLParen, PlacementArgs, PlacementRParen, TypeIdParens, DeclaratorInfo, Initializer.get()); } diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index c0261c462b8834e..10764caf645dbea 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1120,6 +1120,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { case tok::kw_mutable: case tok::kw_namespace: case tok::kw_new: + case tok::kw__placement_new: case tok::kw_operator: case tok::kw_private: case tok::kw_protected: diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 28decc4fc43f9b8..623e3eb4ed70316 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1445,7 +1445,8 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, case tok::coloncolon: { // ::foo::bar const Token &Next = NextToken(); if (Next.isOneOf(tok::kw_new, // ::new - tok::kw_delete)) // ::delete + tok::kw_delete, // ::delete + tok::kw__placement_new)) // ::_placement_new return TPResult::False; [[fallthrough]]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 023411c7edc946b..b8e606b3a45b965 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1875,7 +1875,7 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, /// \param Initializer The initializing expression or initializer-list, or null /// if there is none. ExprResult -Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, +Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, Expr *Initializer) { @@ -1940,7 +1940,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) DirectInitRange = List->getSourceRange(); - return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal, + return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal, IsPlacementNewExpr, PlacementLParen, PlacementArgs, PlacementRParen, TypeIdParens, AllocType, TInfo, ArraySize, DirectInitRange, Initializer); @@ -1997,7 +1997,7 @@ void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, } } -ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, +ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacementNewExpr, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, @@ -2286,9 +2286,10 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool PassAlignment = getLangOpts().AlignedAllocation && Alignment > NewAlignment; + bool HaveDependentPlacementTypes = AllocType->isDependentType() || Expr::hasAnyTypeDependentArguments(PlacementArgs); + AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both; - if (!AllocType->isDependentType() && - !Expr::hasAnyTypeDependentArguments(PlacementArgs) && + if (!HaveDependentPlacementTypes && !IsPlacementNewExpr && FindAllocationFunctions( StartLoc, SourceRange(PlacementLParen, PlacementRParen), Scope, Scope, AllocType, ArraySize.has_value(), PassAlignment, PlacementArgs, @@ -2298,15 +2299,29 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // If this is an array allocation, compute whether the usual array // deallocation function for the type has a size_t parameter. bool UsualArrayDeleteWantsSize = false; - if (ArraySize && !AllocType->isDependentType()) + if (!IsPlacementNewExpr && ArraySize && !AllocType->isDependentType()) UsualArrayDeleteWantsSize = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType); - SmallVector<Expr *, 8> AllPlaceArgs; - if (OperatorNew) { + if (IsPlacementNewExpr && !HaveDependentPlacementTypes) { + assert(PlacementArgs.size() == 1); + assert(UseGlobal); + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, VoidPtr, false); + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), PlacementArgs[0], false, false); + if (ArgE.isInvalid()) + return ExprError(); + + Expr *Arg = ArgE.getAs<Expr>(); + CheckArrayAccess(Arg); + + PlacementArgs[0] = Arg; + } else if (OperatorNew) { auto *Proto = OperatorNew->getType()->castAs<FunctionProtoType>(); VariadicCallType CallType = Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + SmallVector<Expr *, 8> AllPlaceArgs; // We've already converted the placement args, just fill in any default // arguments. Skip the first parameter because we don't have a corresponding @@ -2471,21 +2486,28 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // Mark the new and delete operators as referenced. if (OperatorNew) { + assert(!IsPlacementNewExpr); if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorNew); } if (OperatorDelete) { + assert(!IsPlacementNewExpr); if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) return ExprError(); MarkFunctionReferenced(StartLoc, OperatorDelete); } - return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, - PassAlignment, UsualArrayDeleteWantsSize, - PlacementArgs, TypeIdParens, ArraySize, InitStyle, - Initializer, ResultType, AllocTypeInfo, Range, - DirectInitRange); + if (IsPlacementNewExpr) + return CXXNewExpr::CreatePlacementNew(Context, PlacementArgs[0], TypeIdParens, ArraySize, + InitStyle, Initializer, ResultType, AllocTypeInfo, + Range, DirectInitRange); + else + return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, + PassAlignment, UsualArrayDeleteWantsSize, + PlacementArgs, TypeIdParens, ArraySize, InitStyle, + Initializer, ResultType, AllocTypeInfo, Range, + DirectInitRange); } /// Checks that a type is suitable as the allocated type diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index e24f710fdedd4e2..5fc64fa50dd431b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3343,7 +3343,7 @@ class TreeTransform { /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildCXXNewExpr(SourceLocation StartLoc, bool UseGlobal, + ExprResult RebuildCXXNewExpr(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, @@ -3351,7 +3351,7 @@ class TreeTransform { TypeSourceInfo *AllocatedTypeInfo, std::optional<Expr *> ArraySize, SourceRange DirectInitRange, Expr *Initializer) { - return getSema().BuildCXXNew(StartLoc, UseGlobal, + return getSema().BuildCXXNew(StartLoc, UseGlobal, IsPlacementNewExpr, PlacementLParen, PlacementArgs, PlacementRParen, @@ -12539,7 +12539,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { } return getDerived().RebuildCXXNewExpr( - E->getBeginLoc(), E->isGlobalNew(), + E->getBeginLoc(), E->isGlobalNew(), E->isPlacementNewExpr(), /*FIXME:*/ E->getBeginLoc(), PlacementArgs, /*FIXME:*/ E->getBeginLoc(), E->getTypeIdParens(), AllocType, AllocTypeInfo, ArraySize, E->getDirectInitRange(), NewInit.get()); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index d7d0c0e5bb21b47..7f55e308fa1bb08 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1874,6 +1874,8 @@ void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { E->CXXNewExprBits.UsualArrayDeleteWantsSize = Record.readInt(); E->CXXNewExprBits.StoredInitializationStyle = Record.readInt(); + E->CXXNewExprBits.IsPlacementNewExpr = Record.readInt(); + assert((IsArray == E->isArray()) && "Wrong IsArray!"); assert((HasInit == E->hasInitializer()) && "Wrong HasInit!"); assert((NumPlacementArgs == E->getNumPlacementArgs()) && diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 59be6828fafabf6..2fb5f40e6f448ac 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1799,6 +1799,8 @@ void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->CXXNewExprBits.StoredInitializationStyle); + Record.push_back(E->isPlacementNewExpr()); + Record.AddDeclRef(E->getOperatorNew()); Record.AddDeclRef(E->getOperatorDelete()); Record.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo()); diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp index 99e11a15c08dc2c..e1bdcae0377e7ef 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp @@ -295,7 +295,7 @@ bool PlacementNewChecker::checkPlaceIsAlignedProperly(const CXXNewExpr *NE, void PlacementNewChecker::checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const { // Check only the default placement new. - if (!NE->getOperatorNew()->isReservedGlobalPlacementOperator()) + if (!NE->isReservedPlacementNew()) return; if (NE->getNumPlacementArgs() == 0) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 504fd7f05e0f99b..339b26d44cc8ad0 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -1004,8 +1004,9 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, SVal symVal = UnknownVal(); FunctionDecl *FD = CNE->getOperatorNew(); - bool IsStandardGlobalOpNewFunction = - FD->isReplaceableGlobalAllocationFunction(); + bool IsStandardGlobalOpNewFunction = false; + if (FD) + IsStandardGlobalOpNewFunction = FD->isReplaceableGlobalAllocationFunction(); ProgramStateRef State = Pred->getState(); @@ -1046,7 +1047,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // where new can return NULL. If we end up supporting that option, we can // consider adding a check for it here. // C++11 [basic.stc.dynamic.allocation]p3. - if (const auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) + if (const auto *ProtoType = FD ? FD->getType()->getAs<FunctionProtoType>() : nullptr) if (!ProtoType->isNothrow()) if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>()) State = State->assume(*dSymVal, true); @@ -1099,7 +1100,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // CXXNewExpr, we need to make sure that the constructed object is not // immediately invalidated here. (The placement call should happen before // the constructor call anyway.) - if (FD->isReservedGlobalPlacementOperator()) { + if (CNE->isReservedPlacementNew()) { // Non-array placement new should always return the placement location. SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 69e65e22d61d0d0..7fddd913786cc1e 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -155,6 +155,12 @@ void UnaryExpressions(int *p) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <LValueToRValue> // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' + ::_placement_new (p) int; + // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:24> 'int *' global builtin placement-new expression + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' <BitCast> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' + new (p) int{12}; // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:17> 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(std::size_t, void *)' // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:14, col:17> 'int' @@ -163,6 +169,14 @@ void UnaryExpressions(int *p) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <LValueToRValue> // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' + ::_placement_new (p) int{12}; + // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:30> 'int *' global builtin placement-new expression + // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:27, col:30> 'int' + // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:28> 'int' 12 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' <BitCast> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' + ::delete p; // CHECK: CXXDeleteExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *) noexcept' // CHECK-NEXT: ImplicitCastExpr diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp index e278d9acfe9ee23..7cd3232a295e0a1 100644 --- a/clang/test/CodeGenCXX/new.cpp +++ b/clang/test/CodeGenCXX/new.cpp @@ -219,6 +219,15 @@ namespace test15 { new (p, true) A(); } + // CHECK-LABEL: define{{.*}} void @_ZN6test156test0cEPv( + // CHECK: [[P:%.*]] = load ptr, ptr + // CHECK-NOT: icmp eq ptr [[P]], null + // CHECK-NOT: br i1 + // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[P]]) + void test0c(void *p) { + ::_placement_new (p) A(); + } + // CHECK-LABEL: define{{.*}} void @_ZN6test156test1aEPv( // CHECK: [[P:%.*]] = load ptr, ptr // CHECK-NOT: icmp eq ptr [[P]], null @@ -251,9 +260,24 @@ namespace test15 { new (p, true) A[5]; } + // CHECK-LABEL: define{{.*}} void @_ZN6test156test1cEPv( + // CHECK: [[P:%.*]] = load ptr, ptr + // CHECK-NOT: icmp eq ptr [[P]], null + // CHECK-NOT: br i1 + // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A:.*]], ptr [[P]], i64 5 + // CHECK-NEXT: br label + // CHECK: [[CUR:%.*]] = phi ptr [ [[P]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] + // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[CUR]]) + // CHECK-NEXT: [[NEXT]] = getelementptr inbounds [[A]], ptr [[CUR]], i64 1 + // CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[NEXT]], [[END]] + // CHECK-NEXT: br i1 [[DONE]] + void test1c(void *p) { + ::_placement_new (p) A[5]; + } + // TODO: it's okay if all these size calculations get dropped. // FIXME: maybe we should try to throw on overflow? - // CHECK-LABEL: define{{.*}} void @_ZN6test155test2EPvi( + // CHECK-LABEL: define{{.*}} void @_ZN6test156test2aEPvi( // CHECK: [[N:%.*]] = load i32, ptr // CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64 // CHECK-NEXT: [[P:%.*]] = load ptr, ptr @@ -263,9 +287,25 @@ namespace test15 { // CHECK-NEXT: br label // CHECK: [[CUR:%.*]] = phi ptr [ [[P]], // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[CUR]]) - void test2(void *p, int n) { + void test2a(void *p, int n) { new (p) A[n]; } + + // TODO: it's okay if all these size calculations get dropped. + // FIXME: maybe we should try to throw on overflow? + // CHECK-LABEL: define{{.*}} void @_ZN6test156test2bEPvi( + // CHECK: [[N:%.*]] = load i32, ptr + // CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64 + // CHECK-NEXT: [[P:%.*]] = load ptr, ptr + // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq i64 [[T0]], 0 + // CHECK-NEXT: br i1 [[ISEMPTY]], + // CHECK: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[P]], i64 [[T0]] + // CHECK-NEXT: br label + // CHECK: [[CUR:%.*]] = phi ptr [ [[P]], + // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[CUR]]) + void test2b(void *p, int n) { + ::_placement_new (p) A[n]; + } } namespace PR10197 { diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp index 0270e42b7389fec..20871c6ebc9bdf0 100644 --- a/clang/test/SemaCXX/new-delete.cpp +++ b/clang/test/SemaCXX/new-delete.cpp @@ -58,6 +58,9 @@ void good_news() U *pu = new (ps) U; V *pv = new (ps) V; + U *pu2 = ::_placement_new ((S*)0) U; + int *pi2 = ::_placement_new ((void*)0) int; + pi = new (S(1.0f, 2)) int; (void)new int[true]; @@ -87,6 +90,10 @@ void bad_news(int *ip) (void)new; // expected-error {{expected a type}} (void)new 4; // expected-error {{expected a type}} (void)new () int; // expected-error {{expected expression}} + (void)::_placement_new () int; // expected-error {{expected expression}} + (void)_placement_new (ip) int; // expected-error {{expected expression}} + (void)::_placement_new int; // expected-error {{expected '(' after '::_placement_new'}} + (void)::_placement_new (ip, ip) int; // expected-error {{expected only one argument in placement params}} (void)new int[1.1]; #if __cplusplus <= 199711L // expected-error@-2 {{array size expression must have integral or enumeration type, not 'double'}} >From 2d2e463e10f27f9be21d6cad998e15923ca5f676 Mon Sep 17 00:00:00 2001 From: MaxEW707 <82551778+maxew...@users.noreply.github.com> Date: Tue, 14 Nov 2023 19:15:25 -0500 Subject: [PATCH 2/3] fix formatting errors --- clang/include/clang/AST/ExprCXX.h | 9 ++-- clang/include/clang/Sema/Sema.h | 22 ++++----- clang/lib/AST/ASTImporter.cpp | 12 ++--- clang/lib/AST/ExprCXX.cpp | 31 ++++++------ clang/lib/AST/ExprConstant.cpp | 6 ++- clang/lib/Interpreter/Interpreter.cpp | 13 ++--- clang/lib/Parse/ParseDecl.cpp | 8 +-- clang/lib/Parse/ParseExprCXX.cpp | 10 ++-- clang/lib/Parse/ParseTentative.cpp | 4 +- clang/lib/Sema/SemaExprCXX.cpp | 49 ++++++++++--------- clang/lib/Sema/TreeTransform.h | 17 +++---- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 3 +- 12 files changed, 94 insertions(+), 90 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index d760af796aea28f..b769ddb69c613b5 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2283,8 +2283,8 @@ class CXXNewExpr final SourceRange DirectInitRange); /// Build a c++ builtin placement new expression - CXXNewExpr(Expr *PlacementArg, - SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + CXXNewExpr(Expr *PlacementArg, SourceRange TypeIdParens, + std::optional<Expr *> ArraySize, CXXNewInitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); @@ -2308,8 +2308,9 @@ class CXXNewExpr final static CXXNewExpr * CreatePlacementNew(const ASTContext &Ctx, Expr *PlacementArg, SourceRange TypeIdParens, std::optional<Expr *> ArraySize, - CXXNewInitializationStyle InitializationStyle, Expr *Initializer, - QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + CXXNewInitializationStyle InitializationStyle, + Expr *Initializer, QualType Ty, + TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); /// Create an empty c++ new expression. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ab9a0d0713435b6..ec1d86f7ead5694 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6810,18 +6810,18 @@ class Sema final { bool ListInitialization); /// ActOnCXXNew - Parsed a C++ 'new' expression. - ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, Declarator &D, - Expr *Initializer); ExprResult - BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacementNewExpr, SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - SourceRange TypeIdParens, QualType AllocType, - TypeSourceInfo *AllocTypeInfo, std::optional<Expr *> ArraySize, - SourceRange DirectInitRange, Expr *Initializer); + ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, + SourceLocation PlacementLParen, MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, SourceRange TypeIdParens, + Declarator &D, Expr *Initializer); + ExprResult + BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacementNewExpr, + SourceLocation PlacementLParen, MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, SourceRange TypeIdParens, + QualType AllocType, TypeSourceInfo *AllocTypeInfo, + std::optional<Expr *> ArraySize, SourceRange DirectInitRange, + Expr *Initializer); /// Determine whether \p FD is an aligned allocation or deallocation /// function that is unavailable. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 3204fb69b3440f7..625d86b84ef0b26 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8104,16 +8104,16 @@ ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isPlacementNewExpr()) return CXXNewExpr::CreatePlacementNew( - Importer.getToContext(), ToPlacementArgs[0], ToTypeIdParens, ToArraySize, - E->getInitializationStyle(), ToInitializer, ToType, ToAllocatedTypeSourceInfo, - ToSourceRange, ToDirectInitRange); + Importer.getToContext(), ToPlacementArgs[0], ToTypeIdParens, + ToArraySize, E->getInitializationStyle(), ToInitializer, ToType, + ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange); else return CXXNewExpr::Create( Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(), - ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), - ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, - ToDirectInitRange); + ToPlacementArgs, ToTypeIdParens, ToArraySize, + E->getInitializationStyle(), ToInitializer, ToType, + ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange); } ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 7c7f4c2f31542b9..e47ddc4ab083ce8 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -235,16 +235,17 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, setDependence(computeDependence(this)); } -CXXNewExpr::CXXNewExpr(Expr *PlacementArg, - SourceRange TypeIdParens, std::optional<Expr *> ArraySize, - CXXNewInitializationStyle InitializationStyle, Expr *Initializer, - QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, +CXXNewExpr::CXXNewExpr(Expr *PlacementArg, SourceRange TypeIdParens, + std::optional<Expr *> ArraySize, + CXXNewInitializationStyle InitializationStyle, + Expr *Initializer, QualType Ty, + TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange) : CXXNewExpr(true, nullptr, nullptr, false, false, ArrayRef<Expr *>(&PlacementArg, 1), TypeIdParens, ArraySize, - InitializationStyle, Initializer, Ty, - AllocatedTypeInfo, Range, DirectInitRange) { - CXXNewExprBits.IsPlacementNewExpr = true; + InitializationStyle, Initializer, Ty, AllocatedTypeInfo, Range, + DirectInitRange) { + CXXNewExprBits.IsPlacementNewExpr = true; } CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray, @@ -279,22 +280,20 @@ CXXNewExpr *CXXNewExpr::Create( } CXXNewExpr *CXXNewExpr::CreatePlacementNew( - const ASTContext &Ctx, Expr *PlacementArg, - SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + const ASTContext &Ctx, Expr *PlacementArg, SourceRange TypeIdParens, + std::optional<Expr *> ArraySize, CXXNewInitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange) { bool IsArray = ArraySize.has_value(); bool HasInit = Initializer != nullptr; bool IsParenTypeId = TypeIdParens.isValid(); - void *Mem = - Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>( - IsArray + HasInit + 1, IsParenTypeId), - alignof(CXXNewExpr)); + void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>( + IsArray + HasInit + 1, IsParenTypeId), + alignof(CXXNewExpr)); return new (Mem) - CXXNewExpr(PlacementArg, TypeIdParens, - ArraySize, InitializationStyle, Initializer, Ty, - AllocatedTypeInfo, Range, DirectInitRange); + CXXNewExpr(PlacementArg, TypeIdParens, ArraySize, InitializationStyle, + Initializer, Ty, AllocatedTypeInfo, Range, DirectInitRange); } CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray, diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 7652e22a6a51b4f..8ee1887c6ccf98a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9751,7 +9751,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { bool IsNothrow = false; bool IsPlacement = false; - if (E->isReservedPlacementNew() && Info.CurrentCall->isStdFunction() && !E->isArray()) { + if (E->isReservedPlacementNew() && Info.CurrentCall->isStdFunction() && + !E->isArray()) { // FIXME Support array placement new. assert(E->getNumPlacementArgs() == 1); if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) @@ -9759,7 +9760,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { if (Result.Designator.Invalid) return false; IsPlacement = true; - } else if (E->isPlacementNewExpr() || !OperatorNew->isReplaceableGlobalAllocationFunction()) { + } else if (E->isPlacementNewExpr() || + !OperatorNew->isReplaceableGlobalAllocationFunction()) { Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) << isa<CXXMethodDecl>(OperatorNew) << OperatorNew; return false; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 93ba4a060342a22..f05f5168119aec6 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -604,12 +604,13 @@ class RuntimeInterfaceBuilder SourceLocation(), Args, SourceLocation()); } Expr *Args[] = {AllocCall.get()}; - ExprResult CXXNewCall = S.BuildCXXNew( - E->getSourceRange(), - /*UseGlobal=*/true, /*IsPlacementNewExpr=*/false, - /*PlacementLParen=*/SourceLocation(), Args, /*PlacementRParen=*/SourceLocation(), - /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, - E->getSourceRange(), E); + ExprResult CXXNewCall = + S.BuildCXXNew(E->getSourceRange(), + /*UseGlobal=*/true, /*IsPlacementNewExpr=*/false, + /*PlacementLParen=*/SourceLocation(), Args, + /*PlacementRParen=*/SourceLocation(), + /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, + std::nullopt, E->getSourceRange(), E); assert(!CXXNewCall.isInvalid() && "Can't create runtime placement new call!"); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 18b2fd86e566e5c..c89dfff16c12dde 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5456,8 +5456,8 @@ bool Parser::isTypeSpecifierQualifier() { return isTypeSpecifierQualifier(); case tok::coloncolon: // ::foo::bar - if (NextToken().is(tok::kw_new) || // ::new - NextToken().is(tok::kw_delete) || // ::delete + if (NextToken().is(tok::kw_new) || // ::new + NextToken().is(tok::kw_delete) || // ::delete NextToken().is(tok::kw__placement_new)) // ::_placement_new return false; @@ -5650,8 +5650,8 @@ bool Parser::isDeclarationSpecifier( case tok::coloncolon: // ::foo::bar if (!getLangOpts().CPlusPlus) return false; - if (NextToken().is(tok::kw_new) || // ::new - NextToken().is(tok::kw_delete) || // ::delete + if (NextToken().is(tok::kw_new) || // ::new + NextToken().is(tok::kw_delete) || // ::delete NextToken().is(tok::kw__placement_new)) // ::_placement_new return false; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index f21680834cfc531..1d3433f2d564dca 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -186,7 +186,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier( if (Tok.is(tok::coloncolon)) { // ::new and ::delete aren't nested-name-specifiers. tok::TokenKind NextKind = NextToken().getKind(); - if (NextKind == tok::kw_new || NextKind == tok::kw_delete || NextKind == tok::kw__placement_new) + if (NextKind == tok::kw_new || NextKind == tok::kw_delete || + NextKind == tok::kw__placement_new) return false; if (NextKind == tok::l_brace) { @@ -3171,7 +3172,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, /// ExprResult Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { - assert((Tok.is(tok::kw_new) || Tok.is(tok::kw__placement_new)) && "expected 'new' token"); + assert((Tok.is(tok::kw_new) || Tok.is(tok::kw__placement_new)) && + "expected 'new' token"); const bool IsPlacementNewExpr = Tok.is(tok::kw__placement_new); ConsumeToken(); // Consume 'new' @@ -3308,8 +3310,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { if (Initializer.isInvalid()) return Initializer; - return Actions.ActOnCXXNew(Start, UseGlobal, IsPlacementNewExpr, PlacementLParen, - PlacementArgs, PlacementRParen, + return Actions.ActOnCXXNew(Start, UseGlobal, IsPlacementNewExpr, + PlacementLParen, PlacementArgs, PlacementRParen, TypeIdParens, DeclaratorInfo, Initializer.get()); } diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 623e3eb4ed70316..7d7a044a6b161d3 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1444,8 +1444,8 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, case tok::coloncolon: { // ::foo::bar const Token &Next = NextToken(); - if (Next.isOneOf(tok::kw_new, // ::new - tok::kw_delete, // ::delete + if (Next.isOneOf(tok::kw_new, // ::new + tok::kw_delete, // ::delete tok::kw__placement_new)) // ::_placement_new return TPResult::False; [[fallthrough]]; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b8e606b3a45b965..cf015caffae80ca 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1875,10 +1875,10 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, /// \param Initializer The initializing expression or initializer-list, or null /// if there is none. ExprResult -Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, - SourceLocation PlacementLParen, MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, SourceRange TypeIdParens, - Declarator &D, Expr *Initializer) { +Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + bool IsPlacementNewExpr, SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, SourceLocation PlacementRParen, + SourceRange TypeIdParens, Declarator &D, Expr *Initializer) { std::optional<Expr *> ArraySize; // If the specified type is an array, unwrap it and save the expression. if (D.getNumTypeObjects() > 0 && @@ -1940,10 +1940,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewEx if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) DirectInitRange = List->getSourceRange(); - return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal, IsPlacementNewExpr, - PlacementLParen, PlacementArgs, PlacementRParen, - TypeIdParens, AllocType, TInfo, ArraySize, DirectInitRange, - Initializer); + return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal, + IsPlacementNewExpr, PlacementLParen, PlacementArgs, + PlacementRParen, TypeIdParens, AllocType, TInfo, ArraySize, + DirectInitRange, Initializer); } static bool isLegalArrayNewInitializer(CXXNewInitializationStyle Style, @@ -1997,14 +1997,13 @@ void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, } } -ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacementNewExpr, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, QualType AllocType, - TypeSourceInfo *AllocTypeInfo, - std::optional<Expr *> ArraySize, - SourceRange DirectInitRange, Expr *Initializer) { +ExprResult +Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacementNewExpr, + SourceLocation PlacementLParen, MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, SourceRange TypeIdParens, + QualType AllocType, TypeSourceInfo *AllocTypeInfo, + std::optional<Expr *> ArraySize, SourceRange DirectInitRange, + Expr *Initializer) { SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); SourceLocation StartLoc = Range.getBegin(); @@ -2286,7 +2285,9 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacement bool PassAlignment = getLangOpts().AlignedAllocation && Alignment > NewAlignment; - bool HaveDependentPlacementTypes = AllocType->isDependentType() || Expr::hasAnyTypeDependentArguments(PlacementArgs); + bool HaveDependentPlacementTypes = + AllocType->isDependentType() || + Expr::hasAnyTypeDependentArguments(PlacementArgs); AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both; if (!HaveDependentPlacementTypes && !IsPlacementNewExpr && @@ -2308,10 +2309,12 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacement assert(UseGlobal); QualType VoidPtr = Context.getPointerType(Context.VoidTy); - InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, VoidPtr, false); - ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), PlacementArgs[0], false, false); + InitializedEntity Entity = + InitializedEntity::InitializeParameter(Context, VoidPtr, false); + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), + PlacementArgs[0], false, false); if (ArgE.isInvalid()) - return ExprError(); + return ExprError(); Expr *Arg = ArgE.getAs<Expr>(); CheckArrayAccess(Arg); @@ -2499,9 +2502,9 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool IsPlacement } if (IsPlacementNewExpr) - return CXXNewExpr::CreatePlacementNew(Context, PlacementArgs[0], TypeIdParens, ArraySize, - InitStyle, Initializer, ResultType, AllocTypeInfo, - Range, DirectInitRange); + return CXXNewExpr::CreatePlacementNew( + Context, PlacementArgs[0], TypeIdParens, ArraySize, InitStyle, + Initializer, ResultType, AllocTypeInfo, Range, DirectInitRange); else return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment, UsualArrayDeleteWantsSize, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5fc64fa50dd431b..0c6abd7cad1b9ee 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3343,7 +3343,8 @@ class TreeTransform { /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildCXXNewExpr(SourceLocation StartLoc, bool UseGlobal, bool IsPlacementNewExpr, + ExprResult RebuildCXXNewExpr(SourceLocation StartLoc, bool UseGlobal, + bool IsPlacementNewExpr, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, @@ -3351,16 +3352,10 @@ class TreeTransform { TypeSourceInfo *AllocatedTypeInfo, std::optional<Expr *> ArraySize, SourceRange DirectInitRange, Expr *Initializer) { - return getSema().BuildCXXNew(StartLoc, UseGlobal, IsPlacementNewExpr, - PlacementLParen, - PlacementArgs, - PlacementRParen, - TypeIdParens, - AllocatedType, - AllocatedTypeInfo, - ArraySize, - DirectInitRange, - Initializer); + return getSema().BuildCXXNew( + StartLoc, UseGlobal, IsPlacementNewExpr, PlacementLParen, PlacementArgs, + PlacementRParen, TypeIdParens, AllocatedType, AllocatedTypeInfo, + ArraySize, DirectInitRange, Initializer); } /// Build a new C++ "delete" expression. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 339b26d44cc8ad0..16cd95dfce36efe 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -1047,7 +1047,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // where new can return NULL. If we end up supporting that option, we can // consider adding a check for it here. // C++11 [basic.stc.dynamic.allocation]p3. - if (const auto *ProtoType = FD ? FD->getType()->getAs<FunctionProtoType>() : nullptr) + if (const auto *ProtoType = + FD ? FD->getType()->getAs<FunctionProtoType>() : nullptr) if (!ProtoType->isNothrow()) if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>()) State = State->assume(*dSymVal, true); >From 4f33aa02dfe2997f174a5c6994f0d70129700868 Mon Sep 17 00:00:00 2001 From: MaxEW707 <82551778+maxew...@users.noreply.github.com> Date: Tue, 14 Nov 2023 19:24:42 -0500 Subject: [PATCH 3/3] fix formatting errors --- clang/lib/AST/ExprConstant.cpp | 4 ++-- clang/lib/Parse/ParseDecl.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 8ee1887c6ccf98a..ecf761feca30f6e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3185,8 +3185,8 @@ static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, } /// Get the size of the given type in char units. -static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, - QualType Type, CharUnits &Size) { +static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, QualType Type, + CharUnits &Size) { // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc // extension. if (Type->isVoidType() || Type->isFunctionType()) { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c89dfff16c12dde..bca29fc83b540d5 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3295,7 +3295,7 @@ static void SetupFixedPointError(const LangOptions &LangOpts, bool &isInvalid) { assert(!LangOpts.FixedPoint); DiagID = diag::err_fixed_point_not_enabled; - PrevSpec = ""; // Not used by diagnostic + PrevSpec = ""; // Not used by diagnostic isInvalid = true; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits