From be305674bfd9e559b5e2d9297519124c70c65789 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Fri, 9 Dec 2022 14:17:37 -0800 Subject: [PATCH] Revert "Implement CWG2631" This reverts commit c9a6713b4788f10b81202b70993068e475b392f7. Causes crashes, see D136554. --- clang/docs/ReleaseNotes.rst | 5 - clang/include/clang/AST/ExprCXX.h | 108 ++----- clang/include/clang/AST/Stmt.h | 7 - .../clang/Basic/DiagnosticSemaKinds.td | 4 - clang/include/clang/Sema/Sema.h | 87 +----- clang/lib/AST/ASTImporter.cpp | 21 +- clang/lib/AST/Decl.cpp | 3 +- clang/lib/AST/ExprCXX.cpp | 68 +---- clang/lib/Parse/ParseCXXInlineMethods.cpp | 5 - clang/lib/Parse/ParseDeclCXX.cpp | 6 +- clang/lib/Sema/SemaDeclCXX.cpp | 99 +++++-- clang/lib/Sema/SemaExpr.cpp | 271 ++---------------- clang/lib/Sema/SemaTemplateInstantiate.cpp | 8 +- clang/lib/Sema/TreeTransform.h | 21 +- clang/lib/Sema/UsedDeclVisitor.h | 10 - clang/lib/Serialization/ASTReaderStmt.cpp | 12 +- clang/lib/Serialization/ASTWriterStmt.cpp | 6 - clang/test/CXX/class/class.local/p1-0x.cpp | 4 +- clang/test/CXX/drs/dr26xx.cpp | 16 -- .../CodeGenCXX/builtin-source-location.cpp | 2 - .../default-arguments-with-immediate.cpp | 54 ---- .../CodeGenCXX/meminit-initializers-odr.cpp | 67 ----- .../default-argument-with-immediate-calls.cpp | 34 --- .../cxx11-default-member-initializers.cpp | 10 - .../cxx2a-consteval-default-params.cpp | 81 ------ clang/test/SemaCXX/source_location.cpp | 64 +---- clang/www/cxx_dr_status.html | 2 +- 27 files changed, 156 insertions(+), 919 deletions(-) delete mode 100644 clang/test/CodeGenCXX/default-arguments-with-immediate.cpp delete mode 100644 clang/test/CodeGenCXX/meminit-initializers-odr.cpp delete mode 100644 clang/test/PCH/default-argument-with-immediate-calls.cpp delete mode 100644 clang/test/SemaCXX/cxx2a-consteval-default-params.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6bd038fbdc16f..53155b0e2a492 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -642,11 +642,6 @@ C++ Language Changes in Clang - Implemented DR2358 allowing init captures in lambdas in default arguments. - implemented `DR2654 `_ which undeprecates all compound assignements operations on volatile qualified variables. -- Implemented DR2631. Invalid ``consteval`` calls in default arguments and default - member initializers are diagnosed when and if the default is used. - This Fixes `Issue 56379 `_ - and changes the value of ``std::source_location::current()`` - used in default parameters calls compared to previous versions of Clang. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 9d3fd98f65e29..81267ff568c5b 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1245,12 +1245,8 @@ class CXXThrowExpr : public Expr { /// This wraps up a function call argument that was created from the /// corresponding parameter's default argument, when the call did not /// explicitly supply arguments for all of the parameters. -class CXXDefaultArgExpr final - : public Expr, - private llvm::TrailingObjects { +class CXXDefaultArgExpr final : public Expr { friend class ASTStmtReader; - friend class ASTReader; - friend TrailingObjects; /// The parameter whose default is being used. ParmVarDecl *Param; @@ -1259,7 +1255,7 @@ class CXXDefaultArgExpr final DeclContext *UsedContext; CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param, - Expr *RewrittenExpr, DeclContext *UsedContext) + DeclContext *UsedContext) : Expr(SC, Param->hasUnparsedDefaultArg() ? Param->getType().getNonReferenceType() @@ -1268,58 +1264,28 @@ class CXXDefaultArgExpr final Param->getDefaultArg()->getObjectKind()), Param(Param), UsedContext(UsedContext) { CXXDefaultArgExprBits.Loc = Loc; - CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr; - if (RewrittenExpr) - *getTrailingObjects() = RewrittenExpr; setDependence(computeDependence(this)); } - CXXDefaultArgExpr(EmptyShell Empty, bool HasRewrittenInit) - : Expr(CXXDefaultArgExprClass, Empty) { - CXXDefaultArgExprBits.HasRewrittenInit = HasRewrittenInit; - } - - size_t numTrailingObjects() const { - return CXXDefaultArgExprBits.HasRewrittenInit; - } - public: - static CXXDefaultArgExpr *CreateEmpty(const ASTContext &C, - bool HasRewrittenInit); + CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} // \p Param is the parameter whose default argument is used by this // expression. static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, Expr *RewrittenExpr, - DeclContext *UsedContext); + ParmVarDecl *Param, + DeclContext *UsedContext) { + return new (C) + CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext); + } + // Retrieve the parameter that the argument was created from. const ParmVarDecl *getParam() const { return Param; } ParmVarDecl *getParam() { return Param; } - bool hasRewrittenInit() const { - return CXXDefaultArgExprBits.HasRewrittenInit; - } - - // Retrieve the argument to the function call. - Expr *getExpr(); - const Expr *getExpr() const { - return const_cast(this)->getExpr(); - } - - Expr *getRewrittenExpr() { - return hasRewrittenInit() ? *getTrailingObjects() : nullptr; - } - - const Expr *getRewrittenExpr() const { - return const_cast(this)->getRewrittenExpr(); - } - - // Retrieve the rewritten init expression (for an init expression containing - // immediate calls) with the top level FullExpr and ConstantExpr stripped off. - Expr *getAdjustedRewrittenExpr(); - const Expr *getAdjustedRewrittenExpr() const { - return const_cast(this)->getAdjustedRewrittenExpr(); - } + // Retrieve the actual argument to the function call. + const Expr *getExpr() const { return getParam()->getDefaultArg(); } + Expr *getExpr() { return getParam()->getDefaultArg(); } const DeclContext *getUsedContext() const { return UsedContext; } DeclContext *getUsedContext() { return UsedContext; } @@ -1356,13 +1322,10 @@ class CXXDefaultArgExpr final /// is implicitly used in a mem-initializer-list in a constructor /// (C++11 [class.base.init]p8) or in aggregate initialization /// (C++1y [dcl.init.aggr]p7). -class CXXDefaultInitExpr final - : public Expr, - private llvm::TrailingObjects { - - friend class ASTStmtReader; +class CXXDefaultInitExpr : public Expr { friend class ASTReader; - friend TrailingObjects; + friend class ASTStmtReader; + /// The field whose default is being used. FieldDecl *Field; @@ -1370,29 +1333,16 @@ class CXXDefaultInitExpr final DeclContext *UsedContext; CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, - FieldDecl *Field, QualType Ty, DeclContext *UsedContext, - Expr *RewrittenInitExpr); - - CXXDefaultInitExpr(EmptyShell Empty, bool HasRewrittenInit) - : Expr(CXXDefaultInitExprClass, Empty) { - CXXDefaultInitExprBits.HasRewrittenInit = HasRewrittenInit; - } + FieldDecl *Field, QualType Ty, DeclContext *UsedContext); - size_t numTrailingObjects() const { - return CXXDefaultInitExprBits.HasRewrittenInit; - } + CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} public: - static CXXDefaultInitExpr *CreateEmpty(const ASTContext &C, - bool HasRewrittenInit); /// \p Field is the non-static data member whose default initializer is used /// by this expression. static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc, - FieldDecl *Field, DeclContext *UsedContext, - Expr *RewrittenInitExpr); - - bool hasRewrittenInit() const { - return CXXDefaultInitExprBits.HasRewrittenInit; + FieldDecl *Field, DeclContext *UsedContext) { + return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext); } /// Get the field whose initializer will be used. @@ -1400,23 +1350,13 @@ class CXXDefaultInitExpr final const FieldDecl *getField() const { return Field; } /// Get the initialization expression that will be used. - Expr *getExpr(); const Expr *getExpr() const { - return const_cast(this)->getExpr(); - } - - /// Retrieve the initializing expression with evaluated immediate calls, if - /// any. - const Expr *getRewrittenExpr() const { - assert(hasRewrittenInit() && "expected a rewritten init expression"); - return *getTrailingObjects(); + assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); + return Field->getInClassInitializer(); } - - /// Retrieve the initializing expression with evaluated immediate calls, if - /// any. - Expr *getRewrittenExpr() { - assert(hasRewrittenInit() && "expected a rewritten init expression"); - return *getTrailingObjects(); + Expr *getExpr() { + assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); + return Field->getInClassInitializer(); } const DeclContext *getUsedContext() const { return UsedContext; } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 8781c70abfa26..619d85664476a 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -690,9 +690,6 @@ class alignas(void *) Stmt { unsigned : NumExprBits; - /// Whether this CXXDefaultArgExpr rewrote its argument and stores a copy. - unsigned HasRewrittenInit : 1; - /// The location where the default argument expression was used. SourceLocation Loc; }; @@ -703,10 +700,6 @@ class alignas(void *) Stmt { unsigned : NumExprBits; - /// Whether this CXXDefaultInitExprBitfields rewrote its argument and stores - /// a copy. - unsigned HasRewrittenInit : 1; - /// The location where the default initializer expression was used. SourceLocation Loc; }; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0bbd1f6be4e2e..d85c935f04407 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2646,10 +2646,6 @@ def err_invalid_consteval_take_address : Error< " of an immediate invocation">; def err_invalid_consteval_call : Error< "call to consteval function %q0 is not a constant expression">; -def note_invalid_consteval_initializer : Note< - "in the default initalizer of %0">; -def note_invalid_consteval_initializer_here : Note< - "initialized here %0">; def err_invalid_consteval_decl_kind : Error< "%0 cannot be declared consteval">; def err_invalid_constexpr : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 637bbd7bbd573..d699ef527e3b6 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1330,25 +1330,6 @@ class Sema final { bool InDiscardedStatement; bool InImmediateFunctionContext; - bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false; - - // When evaluating immediate functions in the initializer of a default - // argument or default member initializer, this is the declaration whose - // default initializer is being evaluated and the location of the call - // or constructor definition. - struct InitializationContext { - InitializationContext(SourceLocation Loc, ValueDecl *Decl, - DeclContext *Context) - : Loc(Loc), Decl(Decl), Context(Context) { - assert(Decl && Context && "invalid initialization context"); - } - - SourceLocation Loc; - ValueDecl *Decl = nullptr; - DeclContext *Context = nullptr; - }; - llvm::Optional DelayedDefaultInitializationContext; - ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, CleanupInfo ParentCleanup, @@ -6227,22 +6208,19 @@ class Sema final { bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); - ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr, - SourceLocation InitLoc); - ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field); /// Instantiate or parse a C++ default argument expression as necessary. /// Return true on error. bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param, Expr *Init = nullptr, - bool SkipImmediateInvocations = true); + ParmVarDecl *Param); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. - ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param, Expr *Init = nullptr); + ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, + FunctionDecl *FD, + ParmVarDecl *Param); /// FinalizeVarWithDestructor - Prepare for calling destructor on the /// constructed variable. @@ -9649,63 +9627,6 @@ class Sema final { return ExprEvalContexts.back().isImmediateFunctionContext(); } - bool isCheckingDefaultArgumentOrInitializer() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - const ExpressionEvaluationContextRecord &Ctx = ExprEvalContexts.back(); - return (Ctx.Context == - ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) || - Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer; - } - - bool isCheckingDefaultArgumentOrInitializerOfOuterEntity() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - for (const auto &Ctx : llvm::reverse(ExprEvalContexts)) { - if ((Ctx.Context == - ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) || - Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer) - return true; - if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || - Ctx.isUnevaluated()) - return false; - } - return false; - } - - llvm::Optional - InnermostDeclarationWithDelayedImmediateInvocations() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - for (const auto &Ctx : llvm::reverse(ExprEvalContexts)) { - if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated && - Ctx.DelayedDefaultInitializationContext) - return Ctx.DelayedDefaultInitializationContext; - if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || - Ctx.isUnevaluated()) - break; - } - return llvm::None; - } - - llvm::Optional - OutermostDeclarationWithDelayedImmediateInvocations() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - llvm::Optional - Res; - for (auto &Ctx : llvm::reverse(ExprEvalContexts)) { - if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated && - !Ctx.DelayedDefaultInitializationContext && Res) - break; - if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || - Ctx.isUnevaluated()) - break; - Res = Ctx.DelayedDefaultInitializationContext; - } - return Res; - } - /// RAII class used to determine whether SFINAE has /// trapped any errors that occur during template argument /// deduction. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 2ca6b98fa7780..5fb289b9c9e4c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7687,16 +7687,9 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { if (Error Err = ImportDefaultArgOfParmVarDecl(*FromParam, ToParam)) return std::move(Err); } - Expr *RewrittenInit = nullptr; - if (E->hasRewrittenInit()) { - ExpectedExpr ExprOrErr = import(E->getExpr()); - if (!ExprOrErr) - return ExprOrErr.takeError(); - RewrittenInit = ExprOrErr.get(); - } + return CXXDefaultArgExpr::Create(Importer.getToContext(), *ToUsedLocOrErr, - *ToParamOrErr, RewrittenInit, - *UsedContextOrErr); + *ToParamOrErr, *UsedContextOrErr); } ExpectedStmt @@ -8388,16 +8381,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { ToField->setInClassInitializer(*ToInClassInitializerOrErr); } - Expr *RewrittenInit = nullptr; - if (E->hasRewrittenInit()) { - ExpectedExpr ExprOrErr = import(E->getExpr()); - if (!ExprOrErr) - return ExprOrErr.takeError(); - RewrittenInit = ExprOrErr.get(); - } - return CXXDefaultInitExpr::Create(Importer.getToContext(), *ToBeginLocOrErr, - ToField, *UsedContextOrErr, RewrittenInit); + ToField, *UsedContextOrErr); } ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index c6213a7f59492..bc4cc372d96b6 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2888,7 +2888,8 @@ Expr *ParmVarDecl::getDefaultArg() { Expr *Arg = getInit(); if (auto *E = dyn_cast_or_null(Arg)) - return E->getSubExpr(); + if (!isa(E)) + return E->getSubExpr(); return Arg; } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 8ed95267659f6..b988f0fe13f7f 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -949,43 +949,9 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { return cast(getCalleeDecl())->getLiteralIdentifier(); } -CXXDefaultArgExpr *CXXDefaultArgExpr::CreateEmpty(const ASTContext &C, - bool HasRewrittenInit) { - size_t Size = totalSizeToAlloc(HasRewrittenInit); - auto *Mem = C.Allocate(Size, alignof(CXXDefaultArgExpr)); - return new (Mem) CXXDefaultArgExpr(EmptyShell(), HasRewrittenInit); -} - -CXXDefaultArgExpr *CXXDefaultArgExpr::Create(const ASTContext &C, - SourceLocation Loc, - ParmVarDecl *Param, - Expr *RewrittenExpr, - DeclContext *UsedContext) { - size_t Size = totalSizeToAlloc(RewrittenExpr != nullptr); - auto *Mem = C.Allocate(Size, alignof(CXXDefaultArgExpr)); - return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, - RewrittenExpr, UsedContext); -} - -Expr *CXXDefaultArgExpr::getExpr() { - return CXXDefaultArgExprBits.HasRewrittenInit ? getAdjustedRewrittenExpr() - : getParam()->getDefaultArg(); -} - -Expr *CXXDefaultArgExpr::getAdjustedRewrittenExpr() { - assert(hasRewrittenInit() && - "expected this CXXDefaultArgExpr to have a rewritten init."); - Expr *Init = getRewrittenExpr(); - if (auto *E = dyn_cast_if_present(Init)) - if (!isa(E)) - return E->getSubExpr(); - return Init; -} - CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, FieldDecl *Field, - QualType Ty, DeclContext *UsedContext, - Expr *RewrittenInitExpr) + QualType Ty, DeclContext *UsedContext) : Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx), Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType() ? VK_XValue @@ -993,43 +959,11 @@ CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, /*FIXME*/ OK_Ordinary), Field(Field), UsedContext(UsedContext) { CXXDefaultInitExprBits.Loc = Loc; - CXXDefaultInitExprBits.HasRewrittenInit = RewrittenInitExpr != nullptr; - - if (CXXDefaultInitExprBits.HasRewrittenInit) - *getTrailingObjects() = RewrittenInitExpr; - assert(Field->hasInClassInitializer()); setDependence(computeDependence(this)); } -CXXDefaultInitExpr *CXXDefaultInitExpr::CreateEmpty(const ASTContext &C, - bool HasRewrittenInit) { - size_t Size = totalSizeToAlloc(HasRewrittenInit); - auto *Mem = C.Allocate(Size, alignof(CXXDefaultInitExpr)); - return new (Mem) CXXDefaultInitExpr(EmptyShell(), HasRewrittenInit); -} - -CXXDefaultInitExpr *CXXDefaultInitExpr::Create(const ASTContext &Ctx, - SourceLocation Loc, - FieldDecl *Field, - DeclContext *UsedContext, - Expr *RewrittenInitExpr) { - - size_t Size = totalSizeToAlloc(RewrittenInitExpr != nullptr); - auto *Mem = Ctx.Allocate(Size, alignof(CXXDefaultArgExpr)); - return new (Mem) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), - UsedContext, RewrittenInitExpr); -} - -Expr *CXXDefaultInitExpr::getExpr() { - assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); - if (hasRewrittenInit()) - return getRewrittenExpr(); - - return Field->getInClassInitializer(); -} - CXXTemporary *CXXTemporary::Create(const ASTContext &C, const CXXDestructorDecl *Destructor) { return new (C) CXXTemporary(Destructor); diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 3a7f5426d4a70..d918ea26b9d9d 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -648,11 +648,6 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { Actions.ActOnStartCXXInClassMemberInitializer(); - // The initializer isn't actually potentially evaluated unless it is - // used. - EnterExpressionEvaluationContext Eval( - Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed); - ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, EqualLoc); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 8fb6673b0a45a..53afdd7e7291d 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3188,11 +3188,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, "Data member initializer not starting with '=' or '{'"); EnterExpressionEvaluationContext Context( - Actions, - isa_and_present(D) - ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed - : Sema::ExpressionEvaluationContext::PotentiallyEvaluated, - D); + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 60c3ca7125016..9a80a4874b6db 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4059,21 +4059,6 @@ ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) { return ConstraintExpr; } -ExprResult Sema::ConvertMemberDefaultInitExpression(FieldDecl *FD, - Expr *InitExpr, - SourceLocation InitLoc) { - InitializedEntity Entity = - InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD); - InitializationKind Kind = - FD->getInClassInitStyle() == ICIS_ListInit - ? InitializationKind::CreateDirectList(InitExpr->getBeginLoc(), - InitExpr->getBeginLoc(), - InitExpr->getEndLoc()) - : InitializationKind::CreateCopy(InitExpr->getBeginLoc(), InitLoc); - InitializationSequence Seq(*this, Entity, Kind, InitExpr); - return Seq.Perform(*this, Entity, Kind, InitExpr); -} - /// This is invoked after parsing an in-class initializer for a /// non-static C++ class member, and after instantiating an in-class initializer /// in a class template. Such actions are deferred until the class is complete. @@ -4102,13 +4087,31 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { - Init = ConvertMemberDefaultInitExpression(FD, InitExpr, InitLoc); + InitializedEntity Entity = + InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD); + InitializationKind Kind = + FD->getInClassInitStyle() == ICIS_ListInit + ? InitializationKind::CreateDirectList(InitExpr->getBeginLoc(), + InitExpr->getBeginLoc(), + InitExpr->getEndLoc()) + : InitializationKind::CreateCopy(InitExpr->getBeginLoc(), InitLoc); + InitializationSequence Seq(*this, Entity, Kind, InitExpr); + Init = Seq.Perform(*this, Entity, Kind, InitExpr); if (Init.isInvalid()) { FD->setInvalidDecl(); return; } } + // C++11 [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false); + if (Init.isInvalid()) { + FD->setInvalidDecl(); + return; + } + InitExpr = Init.get(); FD->setInClassInitializer(InitExpr); @@ -15648,6 +15651,70 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, Constructor); } +ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { + assert(Field->hasInClassInitializer()); + + // If we already have the in-class initializer nothing needs to be done. + if (Field->getInClassInitializer()) + return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext); + + // If we might have already tried and failed to instantiate, don't try again. + if (Field->isInvalidDecl()) + return ExprError(); + + // Maybe we haven't instantiated the in-class initializer. Go check the + // pattern FieldDecl to see if it has one. + CXXRecordDecl *ParentRD = cast(Field->getParent()); + + if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) { + CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern(); + DeclContext::lookup_result Lookup = + ClassPattern->lookup(Field->getDeclName()); + + FieldDecl *Pattern = nullptr; + for (auto *L : Lookup) { + if (isa(L)) { + Pattern = cast(L); + break; + } + } + assert(Pattern && "We must have set the Pattern!"); + + if (!Pattern->hasInClassInitializer() || + InstantiateInClassInitializer(Loc, Field, Pattern, + getTemplateInstantiationArgs(Field))) { + // Don't diagnose this again. + Field->setInvalidDecl(); + return ExprError(); + } + return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext); + } + + // DR1351: + // If the brace-or-equal-initializer of a non-static data member + // invokes a defaulted default constructor of its class or of an + // enclosing class in a potentially evaluated subexpression, the + // program is ill-formed. + // + // This resolution is unworkable: the exception specification of the + // default constructor can be needed in an unevaluated context, in + // particular, in the operand of a noexcept-expression, and we can be + // unable to compute an exception specification for an enclosed class. + // + // Any attempt to resolve the exception specification of a defaulted default + // constructor before the initializer is lexically complete will ultimately + // come here at which point we can diagnose it. + RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); + Diag(Loc, diag::err_default_member_initializer_not_yet_parsed) + << OutermostClass << Field; + Diag(Field->getEndLoc(), + diag::note_default_member_initializer_not_yet_parsed); + // Recover by marking the field invalid, unless we're in a SFINAE context. + if (!isSFINAEContext()) + Field->setInvalidDecl(); + return ExprError(); +} + void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; // If initializing the variable failed, don't also diagnose problems with diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index cc5fa79c96ad0..466a17dc1a0ed 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5856,10 +5856,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, } bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param, Expr *RewrittenInit, - bool SkipImmediateInvocations) { + ParmVarDecl *Param) { if (Param->hasUnparsedDefaultArg()) { - assert(!RewrittenInit && "Should not have a rewritten init expression yet"); // If we've already cleared out the location for the default argument, // that means we're parsing it right now. if (!UnparsedDefaultArgLocs.count(Param)) { @@ -5876,14 +5874,11 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, return true; } - if (Param->hasUninstantiatedDefaultArg()) { - assert(!RewrittenInit && "Should not have a rewitten init expression yet"); - if (InstantiateDefaultArgument(CallLoc, FD, Param)) - return true; - } + if (Param->hasUninstantiatedDefaultArg() && + InstantiateDefaultArgument(CallLoc, FD, Param)) + return true; - Expr *Init = RewrittenInit ? RewrittenInit : Param->getInit(); - assert(Init && "default argument but no initializer?"); + assert(Param->hasInit() && "default argument but no initializer?"); // If the default expression creates temporaries, we need to // push them to the current stack of expression temporaries so they'll @@ -5892,252 +5887,34 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, // bound temporaries; see the comment in PR5810. // We don't need to do that with block decls, though, because // blocks in default argument expression can never capture anything. - if (auto *InitWithCleanup = dyn_cast(Init)) { + if (auto Init = dyn_cast(Param->getInit())) { // Set the "needs cleanups" bit regardless of whether there are // any explicit objects. - Cleanup.setExprNeedsCleanups(InitWithCleanup->cleanupsHaveSideEffects()); + Cleanup.setExprNeedsCleanups(Init->cleanupsHaveSideEffects()); + // Append all the objects to the cleanup list. Right now, this // should always be a no-op, because blocks in default argument // expressions should never be able to capture anything. - assert(!InitWithCleanup->getNumObjects() && + assert(!Init->getNumObjects() && "default argument expression has capturing blocks?"); } + + // We already type-checked the argument, so we know it works. + // Just mark all of the declarations in this potentially-evaluated expression + // as being "referenced". EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); - ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = - SkipImmediateInvocations; - MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); + MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), + /*SkipLocalVariables=*/true); return false; } -struct ImmediateCallVisitor : public RecursiveASTVisitor { - bool HasImmediateCalls = false; - - bool shouldVisitImplicitCode() const { return true; } - - bool VisitCallExpr(CallExpr *E) { - if (const FunctionDecl *FD = E->getDirectCallee()) - HasImmediateCalls |= FD->isConsteval(); - return RecursiveASTVisitor::VisitStmt(E); - } - - // SourceLocExpr are not immediate invocations - // but CXXDefaultInitExpr/CXXDefaultArgExpr containing a SourceLocExpr - // need to be rebuilt so that they refer to the correct SourceLocation and - // DeclContext. - bool VisitSourceLocExpr(SourceLocExpr *E) { - HasImmediateCalls = true; - return RecursiveASTVisitor::VisitStmt(E); - } - - // A nested lambda might have parameters with immediate invocations - // in their default arguments. - // The compound statement is not visited (as it does not constitute a - // subexpression). - // FIXME: We should consider visiting and transforming captures - // with init expressions. - bool VisitLambdaExpr(LambdaExpr *E) { - return VisitCXXMethodDecl(E->getCallOperator()); - } - - // Blocks don't support default parameters, and, as for lambdas, - // we don't consider their body a subexpression. - bool VisitBlockDecl(BlockDecl *B) { return false; } - - bool VisitCompoundStmt(CompoundStmt *B) { return false; } - - bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - return TraverseStmt(E->getExpr()); - } - - bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { - return TraverseStmt(E->getExpr()); - } -}; - -struct EnsureImmediateInvocationInDefaultArgs - : TreeTransform { - EnsureImmediateInvocationInDefaultArgs(Sema &SemaRef) - : TreeTransform(SemaRef) {} - - // Lambda can only have immediate invocations in the default - // args of their parameters, which is transformed upon calling the closure. - // The body is not a subexpression, so we have nothing to do. - // FIXME: Immediate calls in capture initializers should be transformed. - ExprResult TransformLambdaExpr(LambdaExpr *E) { return E; } - ExprResult TransformBlockExpr(BlockExpr *E) { return E; } -}; - ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, - FunctionDecl *FD, ParmVarDecl *Param, - Expr *Init) { + FunctionDecl *FD, ParmVarDecl *Param) { assert(Param->hasDefaultArg() && "can't build nonexistent default arg"); - - bool NestedDefaultChecking = - isCheckingDefaultArgumentOrInitializerOfOuterEntity(); - - llvm::Optional - InitializationContext = - OutermostDeclarationWithDelayedImmediateInvocations(); - if (!InitializationContext.has_value()) - InitializationContext.emplace(CallLoc, Param, CurContext); - - if (!Init && !Param->hasUnparsedDefaultArg()) { - // Mark that we are replacing a default argument first. - // If we are instantiating a template we won't have to - // retransform immediate calls. - EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); - ExprEvalContexts.back().DelayedDefaultInitializationContext = { - CallLoc, Param, CurContext}; - - if (Param->hasUninstantiatedDefaultArg()) { - if (InstantiateDefaultArgument(CallLoc, FD, Param)) - return ExprError(); - } else { - // CWG2631 - // An immediate invocation that is not evaluated where it appears is - // evaluated and checked for whether it is a constant expression at the - // point where the enclosing initializer is used in a function call. - ImmediateCallVisitor V; - if (!NestedDefaultChecking) - V.TraverseDecl(Param); - if (V.HasImmediateCalls) { - EnsureImmediateInvocationInDefaultArgs Immediate(*this); - ExprResult Res = Immediate.TransformExpr(Param->getInit()); - if (Res.isInvalid()) - return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), - Res.get()->getBeginLoc()); - if (Res.isInvalid()) - return ExprError(); - Init = Res.get(); - } - } - } - - if (CheckCXXDefaultArgExpr( - CallLoc, FD, Param, Init, - /*SkipImmediateInvocations=*/NestedDefaultChecking)) + if (CheckCXXDefaultArgExpr(CallLoc, FD, Param)) return ExprError(); - - return CXXDefaultArgExpr::Create(Context, InitializationContext->Loc, Param, - Init, InitializationContext->Context); -} - -ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { - assert(Field->hasInClassInitializer()); - - // If we might have already tried and failed to instantiate, don't try again. - if (Field->isInvalidDecl()) - return ExprError(); - - auto *ParentRD = cast(Field->getParent()); - - llvm::Optional - InitializationContext = - OutermostDeclarationWithDelayedImmediateInvocations(); - if (!InitializationContext.has_value()) - InitializationContext.emplace(Loc, Field, CurContext); - - Expr *Init = nullptr; - - bool NestedDefaultChecking = - isCheckingDefaultArgumentOrInitializerOfOuterEntity(); - - if (!Field->getInClassInitializer()) { - // Maybe we haven't instantiated the in-class initializer. Go check the - // pattern FieldDecl to see if it has one. - if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) { - CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern(); - DeclContext::lookup_result Lookup = - ClassPattern->lookup(Field->getDeclName()); - - FieldDecl *Pattern = nullptr; - for (auto *L : Lookup) { - if ((Pattern = dyn_cast(L))) - break; - } - assert(Pattern && "We must have set the Pattern!"); - if (!Pattern->hasInClassInitializer() || - InstantiateInClassInitializer(Loc, Field, Pattern, - getTemplateInstantiationArgs(Field))) { - Field->setInvalidDecl(); - return ExprError(); - } - } - } else { - // CWG2631 - // An immediate invocation that is not evaluated where it appears is - // evaluated and checked for whether it is a constant expression at the - // point where the enclosing initializer is used in a [...] a constructor - // definition, or an aggregate initialization. - EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); - ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, - CurContext}; - - ImmediateCallVisitor V; - if (!NestedDefaultChecking) - V.TraverseDecl(Field); - if (V.HasImmediateCalls) { - EnsureImmediateInvocationInDefaultArgs Immediate(*this); - ExprResult Res = Immediate.TransformExpr(Field->getInClassInitializer()); - if (!Res.isInvalid()) - Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); - if (Res.isInvalid()) { - Field->setInvalidDecl(); - return ExprError(); - } - Init = Res.get(); - } - } - - if (Field->getInClassInitializer()) { - Expr *E = Init ? Init : Field->getInClassInitializer(); - if (!NestedDefaultChecking) { - EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); - MarkDeclarationsReferencedInExpr(E, /*SkipLocalVariables=*/false); - } - // C++11 [class.base.init]p7: - // The initialization of each base and member constitutes a - // full-expression. - ExprResult Res = ActOnFinishFullExpr(E, /*DiscardedValue=*/false); - if (Res.isInvalid()) { - Field->setInvalidDecl(); - return ExprError(); - } - Init = Res.get(); - - return CXXDefaultInitExpr::Create(Context, InitializationContext->Loc, - Field, InitializationContext->Context, - Init); - } - - // DR1351: - // If the brace-or-equal-initializer of a non-static data member - // invokes a defaulted default constructor of its class or of an - // enclosing class in a potentially evaluated subexpression, the - // program is ill-formed. - // - // This resolution is unworkable: the exception specification of the - // default constructor can be needed in an unevaluated context, in - // particular, in the operand of a noexcept-expression, and we can be - // unable to compute an exception specification for an enclosed class. - // - // Any attempt to resolve the exception specification of a defaulted default - // constructor before the initializer is lexically complete will ultimately - // come here at which point we can diagnose it. - RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); - Diag(Loc, diag::err_default_member_initializer_not_yet_parsed) - << OutermostClass << Field; - Diag(Field->getEndLoc(), - diag::note_default_member_initializer_not_yet_parsed); - // Recover by marking the field invalid, unless we're in a SFINAE context. - if (!isSFINAEContext()) - Field->setInvalidDecl(); - return ExprError(); + return CXXDefaultArgExpr::Create(Context, CallLoc, Param, CurContext); } Sema::VariadicCallType @@ -17764,7 +17541,6 @@ void Sema::CheckUnusedVolatileAssignment(Expr *E) { ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) { if (isUnevaluatedContext() || !E.isUsable() || !Decl || !Decl->isConsteval() || isConstantEvaluated() || - isCheckingDefaultArgumentOrInitializer() || RebuildingImmediateInvocation || isImmediateFunctionContext()) return E; @@ -17810,14 +17586,8 @@ static void EvaluateAndDiagnoseImmediateInvocation( FD = Call->getConstructor(); else llvm_unreachable("unhandled decl kind"); - assert(FD && FD->isConsteval()); + assert(FD->isConsteval()); SemaRef.Diag(CE->getBeginLoc(), diag::err_invalid_consteval_call) << FD; - if (auto Context = - SemaRef.InnermostDeclarationWithDelayedImmediateInvocations()) { - SemaRef.Diag(Context->Loc, diag::note_invalid_consteval_initializer) - << Context->Decl; - SemaRef.Diag(Context->Decl->getBeginLoc(), diag::note_declared_at); - } for (auto &Note : Notes) SemaRef.Diag(Note.first, Note.second); return; @@ -19963,8 +19733,7 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { if (auto *FD = dyn_cast(E->getDecl())) if (!isUnevaluatedContext() && !isConstantEvaluated() && - !isImmediateFunctionContext() && - !isCheckingDefaultArgumentOrInitializer() && FD->isConsteval() && + !isImmediateFunctionContext() && FD->isConsteval() && !RebuildingImmediateInvocation && !FD->isDependentContext()) ExprEvalContexts.back().ReferenceToConsteval.insert(E); MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse, diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 11f920ccd2d2f..0c8ae8a927c28 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1979,9 +1979,9 @@ ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( assert(!cast(E->getParam()->getDeclContext())-> getDescribedFunctionTemplate() && "Default arg expressions are never formed in dependent cases."); - return SemaRef.BuildCXXDefaultArgExpr( - E->getUsedLocation(), cast(E->getParam()->getDeclContext()), - E->getParam()); + return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(), + cast(E->getParam()->getDeclContext()), + E->getParam()); } template @@ -3408,8 +3408,6 @@ bool Sema::InstantiateInClassInitializer( ContextRAII SavedContext(*this, Instantiation->getParent()); EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - ExprEvalContexts.back().DelayedDefaultInitializationContext = { - PointOfInstantiation, Instantiation, CurContext}; LocalInstantiationScope Scope(*this, true); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4060278fa8df0..c60c7311bbda5 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3211,10 +3211,9 @@ class TreeTransform { /// By default, builds a new default-argument expression, which does not /// require any semantic analysis. Subclasses may override this routine to /// provide different behavior. - ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, ParmVarDecl *Param, - Expr *RewrittenExpr) { + ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, ParmVarDecl *Param) { return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param, - RewrittenExpr, getSema().CurContext); + getSema().CurContext); } /// Build a new C++11 default-initialization expression. @@ -3224,7 +3223,8 @@ class TreeTransform { /// routine to provide different behavior. ExprResult RebuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { - return getSema().BuildCXXDefaultInitExpr(Loc, Field); + return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field, + getSema().CurContext); } /// Build a new C++ zero-initialization expression. @@ -12163,20 +12163,11 @@ TreeTransform::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { if (!Param) return ExprError(); - ExprResult InitRes; - if (E->hasRewrittenInit()) { - InitRes = getDerived().TransformExpr(E->getRewrittenExpr()); - if (InitRes.isInvalid()) - return ExprError(); - } - if (!getDerived().AlwaysRebuild() && Param == E->getParam() && - E->getUsedContext() == SemaRef.CurContext && - InitRes.get() == E->getRewrittenExpr()) + E->getUsedContext() == SemaRef.CurContext) return E; - return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param, - InitRes.get()); + return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param); } template diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h index f71451703f3ae..24b7342b3fb40 100644 --- a/clang/lib/Sema/UsedDeclVisitor.h +++ b/clang/lib/Sema/UsedDeclVisitor.h @@ -89,16 +89,6 @@ class UsedDeclVisitor : public EvaluatedExprVisitor { asImpl().Visit(E->getExpr()); } - void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { - asImpl().Visit(E->getExpr()); - } - - void VisitInitListExpr(InitListExpr *ILE) { - if (ILE->hasArrayFiller()) - asImpl().Visit(ILE->getArrayFiller()); - Inherited::VisitInitListExpr(ILE); - } - void visitUsedDecl(SourceLocation Loc, Decl *D) { if (auto *CD = dyn_cast(D)) { if (auto *S = CD->getBody()) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 08f9f0bf50d03..2a3c6e7231785 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1824,9 +1824,6 @@ void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { E->Param = readDeclAs(); E->UsedContext = readDeclAs(); E->CXXDefaultArgExprBits.Loc = readSourceLocation(); - E->CXXDefaultArgExprBits.HasRewrittenInit = Record.readInt(); - if (E->CXXDefaultArgExprBits.HasRewrittenInit) - *E->getTrailingObjects() = Record.readSubExpr(); } void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { @@ -1834,9 +1831,6 @@ void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { E->Field = readDeclAs(); E->UsedContext = readDeclAs(); E->CXXDefaultInitExprBits.Loc = readSourceLocation(); - E->CXXDefaultInitExprBits.HasRewrittenInit = Record.readInt(); - if (E->CXXDefaultInitExprBits.HasRewrittenInit) - *E->getTrailingObjects() = Record.readSubExpr(); } void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { @@ -3835,13 +3829,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CXX_DEFAULT_ARG: - S = CXXDefaultArgExpr::CreateEmpty( - Context, /*HasRewrittenInit=*/Record[ASTStmtReader::NumExprFields]); + S = new (Context) CXXDefaultArgExpr(Empty); break; case EXPR_CXX_DEFAULT_INIT: - S = CXXDefaultInitExpr::CreateEmpty( - Context, /*HasRewrittenInit=*/Record[ASTStmtReader::NumExprFields]); + S = new (Context) CXXDefaultInitExpr(Empty); break; case EXPR_CXX_BIND_TEMPORARY: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 6e4101ac122ee..e2ba69ca1eec8 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1745,9 +1745,6 @@ void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Record.AddDeclRef(E->getParam()); Record.AddDeclRef(cast_or_null(E->getUsedContext())); Record.AddSourceLocation(E->getUsedLocation()); - Record.push_back(E->hasRewrittenInit()); - if (E->hasRewrittenInit()) - Record.AddStmt(E->getRewrittenExpr()); Code = serialization::EXPR_CXX_DEFAULT_ARG; } @@ -1756,9 +1753,6 @@ void ASTStmtWriter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { Record.AddDeclRef(E->getField()); Record.AddDeclRef(cast_or_null(E->getUsedContext())); Record.AddSourceLocation(E->getExprLoc()); - Record.push_back(E->hasRewrittenInit()); - if (E->hasRewrittenInit()) - Record.AddStmt(E->getRewrittenExpr()); Code = serialization::EXPR_CXX_DEFAULT_INIT; } diff --git a/clang/test/CXX/class/class.local/p1-0x.cpp b/clang/test/CXX/class/class.local/p1-0x.cpp index 096f5080099ec..49125f5f9b062 100644 --- a/clang/test/CXX/class/class.local/p1-0x.cpp +++ b/clang/test/CXX/class/class.local/p1-0x.cpp @@ -11,8 +11,8 @@ void f() { int x = 3; // expected-note{{'x' declared here}} struct C { int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing lambda expression}} - }c; // expected-note {{required here}} + }; }; - C(); // expected-note {{required here}} + C(); } diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index 68a0e9b2a2688..6aa0e5053bc9a 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -88,19 +88,3 @@ void f() { brachiosaur |= neck; // OK } } - -namespace dr2631 { // dr2631: 16 - constexpr int g(); - consteval int f() { - return g(); - } - int k(int x = f()) { - return x; - } - constexpr int g() { - return 42; - } - int test() { - return k(); - } -} diff --git a/clang/test/CodeGenCXX/builtin-source-location.cpp b/clang/test/CodeGenCXX/builtin-source-location.cpp index 7af6749d0d6d6..6e44e6b0e60e3 100644 --- a/clang/test/CodeGenCXX/builtin-source-location.cpp +++ b/clang/test/CodeGenCXX/builtin-source-location.cpp @@ -1,6 +1,4 @@ // RUN: %clang_cc1 -no-opaque-pointers -std=c++2a -fblocks %s -triple x86_64-unknown-unknown -emit-llvm -o %t.ll -// RUN: %clang_cc1 -no-opaque-pointers -std=c++14 -fblocks %s -triple x86_64-unknown-unknown -emit-llvm -o %t.ll - // This needs to be performed before #line directives which alter filename // RUN: %clang_cc1 -no-opaque-pointers -fno-file-reproducible -fmacro-prefix-map=%p=/UNLIKELY/PATH -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-PREFIX-MAP diff --git a/clang/test/CodeGenCXX/default-arguments-with-immediate.cpp b/clang/test/CodeGenCXX/default-arguments-with-immediate.cpp deleted file mode 100644 index 54a02ffc06836..0000000000000 --- a/clang/test/CodeGenCXX/default-arguments-with-immediate.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -triple x86_64-elf-gnu %s -emit-llvm -o - | FileCheck %s - -consteval int immediate() { return 0;} -static int ext(); -void f(int a = immediate() + ext()); - -void test_function() { - f(); - f(0); - // CHECK: call noundef i32 @_ZL3extv() - // CHECK: add - // CHECK: call {{.*}} @_Z1fi - // CHECK: call {{.*}} @_Z1fi -} - -// CHECK: define {{.*}} i32 @_ZL3extv() - -static constexpr int not_immediate(); -struct A { - int a = immediate() + not_immediate(); -}; - -void test_member() { - // CHECK: call void @_ZN1AC2Ev - A defaulted; - // CHECK-NOT: call void @_ZN1AC2Ev - A provided{0}; -} - -// CHECK: define {{.*}} void @_ZN1AC2Ev{{.*}} -// CHECK: %call = call noundef i32 @_ZL13not_immediatev() - -int never_referenced() {return 42;}; - - -namespace not_used { - -struct A { - int a = immediate() + never_referenced(); -}; -void f(int a = immediate() + never_referenced()); - -void g() { - A a{0}; - f(0); -} - -} - -static int ext() {return 0;} -static constexpr int not_immediate() {return 0;} - -// CHECK-NOT: define {{.*}} i32 _ZL16never_referencedv()( -// CHECK: define {{.*}} i32 @_ZL13not_immediatev() diff --git a/clang/test/CodeGenCXX/meminit-initializers-odr.cpp b/clang/test/CodeGenCXX/meminit-initializers-odr.cpp deleted file mode 100644 index abbcdee57df73..0000000000000 --- a/clang/test/CodeGenCXX/meminit-initializers-odr.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s - -struct ThisShouldBeCalled { - ThisShouldBeCalled() {} -}; - -template -struct ThisShouldBeCalledTPL { - ThisShouldBeCalledTPL() {} -}; - -consteval int f () { - return 42; -} - -struct WithConsteval { - WithConsteval(int x = f()) {} -}; - -template -struct WithConstevalTPL { - WithConstevalTPL(T x = f()) {} -}; - - -struct Base { - ThisShouldBeCalled y = {}; -}; - -struct S : Base { - ThisShouldBeCalledTPL A = {}; - WithConsteval B = {}; - WithConstevalTPL C = {}; -}; -void Do(S = S{}) {} - -void test() { - Do(); -} - -// CHECK-LABEL: @_ZN18ThisShouldBeCalledC2Ev -// CHECK-LABEL: @_ZN21ThisShouldBeCalledTPLIiEC2Ev -// CHECK-LABEL: @_ZN13WithConstevalC2Ei -// CHECK-LABEL: @_ZN16WithConstevalTPLIdEC2Ed - -namespace check_arrays { - -template -struct inner { - inner() {} -}; - -struct S { - inner a {}; -}; - -class C { - S s[1]{}; -}; - -int f() { - C c; -} - -// CHECK-LABEL: @_ZN12check_arrays5innerIiEC2Ev - -} diff --git a/clang/test/PCH/default-argument-with-immediate-calls.cpp b/clang/test/PCH/default-argument-with-immediate-calls.cpp deleted file mode 100644 index 510605a23d4e7..0000000000000 --- a/clang/test/PCH/default-argument-with-immediate-calls.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// RUN: %clang_cc1 -std=c++20 -emit-pch %s -o %t -// RUN: %clang_cc1 -std=c++20 -include-pch %t -verify %s -// expected-no-diagnostics - -#ifndef HEADER_INCLUDED -#define HEADER_INCLUDED - -consteval int immediate(); -int regular_function() { - return 0; -} - -struct S { - int a = immediate() + regular_function(); -}; - -int f(int arg = immediate()) { - return arg; -} - -#else - -consteval int immediate() { - return 0; -} - -void test() { - f(0); - f(); - S s{0}; - S t{0}; -} - -#endif diff --git a/clang/test/SemaCXX/cxx11-default-member-initializers.cpp b/clang/test/SemaCXX/cxx11-default-member-initializers.cpp index d32ff48bf0ce0..9353e633fafbc 100644 --- a/clang/test/SemaCXX/cxx11-default-member-initializers.cpp +++ b/clang/test/SemaCXX/cxx11-default-member-initializers.cpp @@ -12,13 +12,3 @@ namespace PR31692 { // A::X can now be default-constructed. static_assert(__is_constructible(A::X), ""); } - - -struct S { -} constexpr s; -struct C { - C(S); -}; -class MemInit { - C m = s; -}; diff --git a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp b/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp deleted file mode 100644 index abeb27fd03e35..0000000000000 --- a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2b %s - -consteval int undefined(); // expected-note 4 {{declared here}} - -void check_lambdas_unused( - int a = [] - { - // The body of a lambda is not a subexpression of the lambda - // so this is immediately evaluated even if the parameter - // is never used. - return undefined(); // expected-error {{not a constant expression}} \ - // expected-note {{undefined function 'undefined'}} - }(), - int b = [](int no_error = undefined()) { - return no_error; - }(0), - int c = [](int defaulted = undefined()) { - return defaulted; - }() -) {} - -int check_lambdas_used( - int b = [](int no_error = undefined()) { - return no_error; - }(0), - int c = [](int defaulted = undefined()) { // expected-error {{not a constant expression}} \ - // expected-note {{declared here}} \ - // expected-note {{undefined function 'undefined'}} - return defaulted; - }(), // expected-note {{in the default initalizer of 'defaulted'}} - int d = [](int defaulted = sizeof(undefined())) { - return defaulted; - }() -) { - return 0; -} - -int test_check_lambdas_used = check_lambdas_used(); - -struct UnusedInitWithLambda { - int a = [] { - return undefined(); // expected-error {{not a constant expression}} \ - // expected-note {{undefined function 'undefined'}} - }(); - // UnusedInitWithLambda is never constructed, so the initializer - // of b and undefined() are never evaluated. - int b = [](int no_error = undefined()) { - return no_error; - }(); -}; - -consteval int ub(int n) { - return 0/n; // expected-note {{division}} -} - -struct InitWithLambda { - int b = [](int error = undefined()) { // expected-error {{not a constant expression}} \ - // expected-note {{declared here}} \ - // expected-note {{undefined function 'undefined'}} - return error; - }(); // expected-note {{in the default initalizer of 'error'}} - int c = [](int error = sizeof(undefined()) + ub(0)) { // expected-error {{'ub' is not a constant expression}} \ - // expected-note {{declared here}} \ - // expected-note {{in call to 'ub(0)}} - return error; - }(); // expected-note {{in the default initalizer of 'error'}} -} i; // expected-note {{in implicit default constructor}} - -namespace ShouldNotCrash { - template - struct F { - template - F(const U&) {} - }; - struct A { - static constexpr auto x = [] {}; - F f = x; - }; - void f(A a = A()) { } -} diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp index 9cfe9207dd14d..ccb385f60dc4b 100644 --- a/clang/test/SemaCXX/source_location.cpp +++ b/clang/test/SemaCXX/source_location.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s -// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -verify %s // expected-no-diagnostics #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42) @@ -9,22 +8,15 @@ template struct Printer; -#ifdef USE_CONSTEVAL -#define SOURCE_LOC_EVAL_KIND consteval -#else -#define SOURCE_LOC_EVAL_KIND constexpr -#endif - namespace std { class source_location { struct __impl; public: - static SOURCE_LOC_EVAL_KIND source_location - current(const __impl *__p = __builtin_source_location()) noexcept { - source_location __loc; - __loc.__m_impl = __p; - return __loc; + static constexpr source_location current(const __impl *__p = __builtin_source_location()) noexcept { + source_location __loc; + __loc.__m_impl = __p; + return __loc; } constexpr source_location() = default; constexpr source_location(source_location const &) = default; @@ -601,51 +593,3 @@ namespace TestConstexprContext { } static_assert(test()); } - -namespace Lambda { -#line 8000 "TestLambda.cpp" -constexpr int nested_lambda(int l = []{ - return SL::current().line(); -}()) { - return l; -} -static_assert(nested_lambda() == __LINE__ - 4); - -constexpr int lambda_param(int l = [](int l = SL::current().line()) { - return l; -}()) { - return l; -} -static_assert(lambda_param() == __LINE__); - - -} - -constexpr int compound_literal_fun(int a = - (int){ SL::current().line() } -) { return a ;} -static_assert(compound_literal_fun() == __LINE__); - -struct CompoundLiteral { - int a = (int){ SL::current().line() }; -}; -static_assert(CompoundLiteral{}.a == __LINE__); - - -// FIXME -// Init captures are subexpressions of the lambda expression -// so according to the standard immediate invocations in init captures -// should be evaluated at the call site. -// However Clang does not yet implement this as it would introduce -// a fair bit of complexity. -// We intend to implement that functionality once we find real world -// use cases that require it. -constexpr int test_init_capture(int a = - [b = SL::current().line()] { return b; }()) { - return a; -} -#ifdef USE_CONSTEVAL -static_assert(test_init_capture() == __LINE__ - 4); -#else -static_assert(test_init_capture() == __LINE__ ); -#endif diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 1c880bab52957..f131df751d0ef 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -15593,7 +15593,7 @@

C++ defect report implementation status

2631 DR Immediate function evaluations in default arguments - Clang 16 + Unknown 2632