diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp index 616e57efa76de..71fd8eca300c1 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -323,8 +323,7 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag, return false; }; switch (New->getInitializationStyle()) { - case CXXNewInitializationStyle::None: - case CXXNewInitializationStyle::Implicit: { + case CXXNewExpr::NoInit: { if (ArraySizeExpr.empty()) { Diag << FixItHint::CreateRemoval(SourceRange(NewStart, NewEnd)); } else { @@ -335,7 +334,7 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag, } break; } - case CXXNewInitializationStyle::Call: { + case CXXNewExpr::CallInit: { // FIXME: Add fixes for constructors with parameters that can be created // with a C++11 braced-init-list (e.g. std::vector, std::map). // Unlike ordinal cases, braced list can not be deduced in @@ -372,7 +371,7 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag, } break; } - case CXXNewInitializationStyle::List: { + case CXXNewExpr::ListInit: { // Range of the substring that we do not want to remove. SourceRange InitRange; if (const auto *NewConstruct = New->getConstructExpr()) { diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 37d310ef967d9..a106bafcfa3e0 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2206,20 +2206,6 @@ class CXXScalarValueInitExpr : public Expr { } }; -enum class CXXNewInitializationStyle { - /// New-expression has no initializer as written. - None, - - /// New-expression has no written initializer, but has an implicit one. - Implicit, - - /// New-expression has a C++98 paren-delimited initializer. - Call, - - /// New-expression has a C++11 list-initializer. - List -}; - /// Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". class CXXNewExpr final @@ -2273,12 +2259,25 @@ class CXXNewExpr final return isParenTypeId(); } +public: + enum InitializationStyle { + /// New-expression has no initializer as written. + NoInit, + + /// New-expression has a C++98 paren-delimited initializer. + CallInit, + + /// New-expression has a C++11 list-initializer. + ListInit + }; + +private: /// Build a c++ new expression. CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, ArrayRef PlacementArgs, SourceRange TypeIdParens, std::optional ArraySize, - CXXNewInitializationStyle InitializationStyle, Expr *Initializer, + InitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); @@ -2293,7 +2292,7 @@ class CXXNewExpr final FunctionDecl *OperatorDelete, bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, ArrayRef PlacementArgs, SourceRange TypeIdParens, std::optional ArraySize, - CXXNewInitializationStyle InitializationStyle, Expr *Initializer, + InitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange); @@ -2389,20 +2388,15 @@ class CXXNewExpr final /// Whether this new-expression has any initializer at all. bool hasInitializer() const { - switch (getInitializationStyle()) { - case CXXNewInitializationStyle::None: - return false; - case CXXNewInitializationStyle::Implicit: - case CXXNewInitializationStyle::Call: - case CXXNewInitializationStyle::List: - return true; - } + return CXXNewExprBits.StoredInitializationStyle > 0; } /// The kind of initializer this new-expression has. - CXXNewInitializationStyle getInitializationStyle() const { - return static_cast( - CXXNewExprBits.StoredInitializationStyle); + InitializationStyle getInitializationStyle() const { + if (CXXNewExprBits.StoredInitializationStyle == 0) + return NoInit; + return static_cast( + CXXNewExprBits.StoredInitializationStyle - 1); } /// The initializer of this new-expression. diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 83af7998f6833..4d2e0e9a945a7 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -184,7 +184,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, bool UsualArrayDeleteWantsSize, ArrayRef PlacementArgs, SourceRange TypeIdParens, std::optional ArraySize, - CXXNewInitializationStyle InitializationStyle, + InitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange) @@ -193,9 +193,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, AllocatedTypeInfo(AllocatedTypeInfo), Range(Range), DirectInitRange(DirectInitRange) { - assert((Initializer != nullptr || - InitializationStyle == CXXNewInitializationStyle::None || - InitializationStyle == CXXNewInitializationStyle::Implicit) && + assert((Initializer != nullptr || InitializationStyle == NoInit) && "Only NoInit can have no initializer!"); CXXNewExprBits.IsGlobalNew = IsGlobalNew; @@ -203,7 +201,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment; CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; CXXNewExprBits.StoredInitializationStyle = - llvm::to_underlying(InitializationStyle); + Initializer ? InitializationStyle + 1 : 0; bool IsParenTypeId = TypeIdParens.isValid(); CXXNewExprBits.IsParenTypeId = IsParenTypeId; CXXNewExprBits.NumPlacementArgs = PlacementArgs.size(); @@ -219,10 +217,10 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, getTrailingObjects()[0] = TypeIdParens; switch (getInitializationStyle()) { - case CXXNewInitializationStyle::Call: + case CallInit: this->Range.setEnd(DirectInitRange.getEnd()); break; - case CXXNewInitializationStyle::List: + case ListInit: this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break; default: @@ -242,14 +240,15 @@ CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray, CXXNewExprBits.IsParenTypeId = IsParenTypeId; } -CXXNewExpr *CXXNewExpr::Create( - const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, - FunctionDecl *OperatorDelete, bool ShouldPassAlignment, - bool UsualArrayDeleteWantsSize, ArrayRef PlacementArgs, - SourceRange TypeIdParens, std::optional ArraySize, - CXXNewInitializationStyle InitializationStyle, Expr *Initializer, - QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, - SourceRange DirectInitRange) { +CXXNewExpr * +CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew, + FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, + bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, + ArrayRef PlacementArgs, SourceRange TypeIdParens, + std::optional ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, + SourceRange Range, SourceRange DirectInitRange) { bool IsArray = ArraySize.has_value(); bool HasInit = Initializer != nullptr; unsigned NumPlacementArgs = PlacementArgs.size(); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 5ac8c2e447cdb..8530675ca2a1c 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4826,7 +4826,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, Out << '_'; mangleType(New->getAllocatedType()); if (New->hasInitializer()) { - if (New->getInitializationStyle() == CXXNewInitializationStyle::List) + if (New->getInitializationStyle() == CXXNewExpr::ListInit) Out << "il"; else Out << "pi"; @@ -4840,8 +4840,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, } else if (const ParenListExpr *PLE = dyn_cast(Init)) { for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i) mangleExpression(PLE->getExpr(i)); - } else if (New->getInitializationStyle() == - CXXNewInitializationStyle::List && + } else if (New->getInitializationStyle() == CXXNewExpr::ListInit && isa(Init)) { // Only take InitListExprs apart for list-initialization. mangleInitListElements(cast(Init)); diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index bc7bc7337b15e..1a013b45c615d 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1351,15 +1351,9 @@ void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { attributeOnlyIfTrue("isArray", NE->isArray()); attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); switch (NE->getInitializationStyle()) { - case CXXNewInitializationStyle::None: - case CXXNewInitializationStyle::Implicit: - break; - case CXXNewInitializationStyle::Call: - JOS.attribute("initStyle", "call"); - break; - case CXXNewInitializationStyle::List: - JOS.attribute("initStyle", "list"); - break; + case CXXNewExpr::NoInit: break; + case CXXNewExpr::CallInit: JOS.attribute("initStyle", "call"); break; + case CXXNewExpr::ListInit: JOS.attribute("initStyle", "list"); break; } if (const FunctionDecl *FD = NE->getOperatorNew()) JOS.attribute("operatorNewDecl", createBareDeclRef(FD)); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index ab4a013de5f55..44dc9d3780f35 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2298,10 +2298,9 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isParenTypeId()) OS << ")"; - CXXNewInitializationStyle InitStyle = E->getInitializationStyle(); - if (InitStyle != CXXNewInitializationStyle::None && - InitStyle != CXXNewInitializationStyle::Implicit) { - bool Bare = InitStyle == CXXNewInitializationStyle::Call && + CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle(); + if (InitStyle != CXXNewExpr::NoInit) { + bool Bare = InitStyle == CXXNewExpr::CallInit && !isa(E->getInitializer()); if (Bare) OS << "("; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8128219dd6f63..6510fa369d78e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2096,7 +2096,7 @@ void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) { ID.AddInteger(S->getNumPlacementArgs()); ID.AddBoolean(S->isGlobalNew()); ID.AddBoolean(S->isParenTypeId()); - ID.AddInteger(llvm::to_underlying(S->getInitializationStyle())); + ID.AddInteger(S->getInitializationStyle()); } void diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d947aba70d8f3..25d7759cc168d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1946,7 +1946,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, Initializer); } -static bool isLegalArrayNewInitializer(CXXNewInitializationStyle Style, +static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, Expr *Init) { if (!Init) return true; @@ -1957,7 +1957,7 @@ static bool isLegalArrayNewInitializer(CXXNewInitializationStyle Style, else if (CXXConstructExpr *CCE = dyn_cast(Init)) return !CCE->isListInitialization() && CCE->getConstructor()->isDefaultConstructor(); - else if (Style == CXXNewInitializationStyle::List) { + else if (Style == CXXNewExpr::ListInit) { assert(isa(Init) && "Shouldn't create list CXXConstructExprs for arrays."); return true; @@ -2008,49 +2008,44 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); SourceLocation StartLoc = Range.getBegin(); - CXXNewInitializationStyle InitStyle; + CXXNewExpr::InitializationStyle initStyle; if (DirectInitRange.isValid()) { assert(Initializer && "Have parens but no initializer."); - InitStyle = CXXNewInitializationStyle::Call; + initStyle = CXXNewExpr::CallInit; } else if (Initializer && isa(Initializer)) - InitStyle = CXXNewInitializationStyle::List; + initStyle = CXXNewExpr::ListInit; else { assert((!Initializer || isa(Initializer) || isa(Initializer)) && "Initializer expression that cannot have been implicitly created."); - InitStyle = CXXNewInitializationStyle::None; + initStyle = CXXNewExpr::NoInit; } MultiExprArg Exprs(&Initializer, Initializer ? 1 : 0); if (ParenListExpr *List = dyn_cast_or_null(Initializer)) { - assert(InitStyle == CXXNewInitializationStyle::Call && - "paren init for non-call init"); + assert(initStyle == CXXNewExpr::CallInit && "paren init for non-call init"); Exprs = MultiExprArg(List->getExprs(), List->getNumExprs()); } // C++11 [expr.new]p15: // A new-expression that creates an object of type T initializes that // object as follows: - InitializationKind Kind = [&] { - switch (InitStyle) { - // - If the new-initializer is omitted, the object is default- - // initialized (8.5); if no initialization is performed, - // the object has indeterminate value - case CXXNewInitializationStyle::None: - case CXXNewInitializationStyle::Implicit: - return InitializationKind::CreateDefault(TypeRange.getBegin()); - // - Otherwise, the new-initializer is interpreted according to the - // initialization rules of 8.5 for direct-initialization. - case CXXNewInitializationStyle::Call: - return InitializationKind::CreateDirect(TypeRange.getBegin(), - DirectInitRange.getBegin(), - DirectInitRange.getEnd()); - case CXXNewInitializationStyle::List: - return InitializationKind::CreateDirectList(TypeRange.getBegin(), - Initializer->getBeginLoc(), - Initializer->getEndLoc()); - } - }(); + InitializationKind Kind + // - If the new-initializer is omitted, the object is default- + // initialized (8.5); if no initialization is performed, + // the object has indeterminate value + = initStyle == CXXNewExpr::NoInit + ? InitializationKind::CreateDefault(TypeRange.getBegin()) + // - Otherwise, the new-initializer is interpreted according to + // the + // initialization rules of 8.5 for direct-initialization. + : initStyle == CXXNewExpr::ListInit + ? InitializationKind::CreateDirectList( + TypeRange.getBegin(), Initializer->getBeginLoc(), + Initializer->getEndLoc()) + : InitializationKind::CreateDirect(TypeRange.getBegin(), + DirectInitRange.getBegin(), + DirectInitRange.getEnd()); // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. auto *Deduced = AllocType->getContainedDeducedType(); @@ -2071,14 +2066,13 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, return ExprError(); } else if (Deduced && !Deduced->isDeduced()) { MultiExprArg Inits = Exprs; - bool Braced = (InitStyle == CXXNewInitializationStyle::List); + bool Braced = (initStyle == CXXNewExpr::ListInit); if (Braced) { auto *ILE = cast(Exprs[0]); Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits()); } - if (InitStyle == CXXNewInitializationStyle::None || - InitStyle == CXXNewInitializationStyle::Implicit || Inits.empty()) + if (initStyle == CXXNewExpr::NoInit || Inits.empty()) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); if (Inits.size() > 1) { @@ -2402,7 +2396,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // Array 'new' can't have any initializers except empty parentheses. // Initializer lists are also allowed, in C++11. Rely on the parser for the // dialect distinction. - if (ArraySize && !isLegalArrayNewInitializer(InitStyle, Initializer)) { + if (ArraySize && !isLegalArrayNewInitializer(initStyle, Initializer)) { SourceRange InitRange(Exprs.front()->getBeginLoc(), Exprs.back()->getEndLoc()); Diag(StartLoc, diag::err_new_array_init_args) << InitRange; @@ -2474,7 +2468,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment, UsualArrayDeleteWantsSize, - PlacementArgs, TypeIdParens, ArraySize, InitStyle, + PlacementArgs, TypeIdParens, ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, Range, DirectInitRange); }