Skip to content

Commit

Permalink
Revert "Implement CWG2631"
Browse files Browse the repository at this point in the history
This reverts commit c9a6713.

Causes crashes, see D136554.
  • Loading branch information
aeubanks committed Dec 9, 2022
1 parent afe3558 commit be30567
Show file tree
Hide file tree
Showing 27 changed files with 156 additions and 919 deletions.
5 changes: 0 additions & 5 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -642,11 +642,6 @@ C++ Language Changes in Clang
- Implemented DR2358 allowing init captures in lambdas in default arguments.
- implemented `DR2654 <https://wg21.link/cwg2654>`_ 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 <https://github.com/llvm/llvm-project/issues/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
^^^^^^^^^^^^^^^^^^^^^
Expand Down
108 changes: 24 additions & 84 deletions clang/include/clang/AST/ExprCXX.h
Expand Up @@ -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<CXXDefaultArgExpr, Expr *> {
class CXXDefaultArgExpr final : public Expr {
friend class ASTStmtReader;
friend class ASTReader;
friend TrailingObjects;

/// The parameter whose default is being used.
ParmVarDecl *Param;
Expand All @@ -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()
Expand All @@ -1268,58 +1264,28 @@ class CXXDefaultArgExpr final
Param->getDefaultArg()->getObjectKind()),
Param(Param), UsedContext(UsedContext) {
CXXDefaultArgExprBits.Loc = Loc;
CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr;
if (RewrittenExpr)
*getTrailingObjects<Expr *>() = 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<CXXDefaultArgExpr *>(this)->getExpr();
}

Expr *getRewrittenExpr() {
return hasRewrittenInit() ? *getTrailingObjects<Expr *>() : nullptr;
}

const Expr *getRewrittenExpr() const {
return const_cast<CXXDefaultArgExpr *>(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<CXXDefaultArgExpr *>(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; }
Expand Down Expand Up @@ -1356,67 +1322,41 @@ 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<CXXDefaultArgExpr, Expr *> {

friend class ASTStmtReader;
class CXXDefaultInitExpr : public Expr {
friend class ASTReader;
friend TrailingObjects;
friend class ASTStmtReader;

/// The field whose default is being used.
FieldDecl *Field;

/// The context where the default initializer expression was used.
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.
FieldDecl *getField() { return Field; }
const FieldDecl *getField() const { return Field; }

/// Get the initialization expression that will be used.
Expr *getExpr();
const Expr *getExpr() const {
return const_cast<CXXDefaultInitExpr *>(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<Expr *>();
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 *>();
Expr *getExpr() {
assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
return Field->getInClassInitializer();
}

const DeclContext *getUsedContext() const { return UsedContext; }
Expand Down
7 changes: 0 additions & 7 deletions clang/include/clang/AST/Stmt.h
Expand Up @@ -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;
};
Expand All @@ -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;
};
Expand Down
4 changes: 0 additions & 4 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -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<
Expand Down
87 changes: 4 additions & 83 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -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<InitializationContext> DelayedDefaultInitializationContext;

ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
unsigned NumCleanupObjects,
CleanupInfo ParentCleanup,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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<ExpressionEvaluationContextRecord::InitializationContext>
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<ExpressionEvaluationContextRecord::InitializationContext>
OutermostDeclarationWithDelayedImmediateInvocations() const {
assert(!ExprEvalContexts.empty() &&
"Must be in an expression evaluation context");
llvm::Optional<ExpressionEvaluationContextRecord::InitializationContext>
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.
Expand Down
21 changes: 3 additions & 18 deletions clang/lib/AST/ASTImporter.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Decl.cpp
Expand Up @@ -2888,7 +2888,8 @@ Expr *ParmVarDecl::getDefaultArg() {

Expr *Arg = getInit();
if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
return E->getSubExpr();
if (!isa<ConstantExpr>(E))
return E->getSubExpr();

return Arg;
}
Expand Down

0 comments on commit be30567

Please sign in to comment.