diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -43,7 +43,9 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CurrentSourceLocExprScope.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/OSLog.h" #include "clang/AST/OptionalDiagnostic.h" #include "clang/AST/RecordLayout.h" @@ -926,6 +928,8 @@ /// later on (such as a use of an undefined global). bool CheckingPotentialConstantExpression = false; + /// TODO: add doc. + bool AccessingStaticConstantDataMember = false; /// Whether we're checking for an expression that has undefined behavior. /// If so, we will produce warnings if we encounter an operation that is /// always undefined. @@ -8449,6 +8453,9 @@ // Handle static member functions. if (const CXXMethodDecl *MD = dyn_cast(E->getMemberDecl())) { if (MD->isStatic()) { + llvm::SaveAndRestore StaticMember(Info.AccessingStaticConstantDataMember); + if(Info.InConstantContext) + Info.AccessingStaticConstantDataMember = true; VisitIgnoredBaseExpression(E->getBase()); return Success(MD); } @@ -8730,6 +8737,9 @@ if (Info.checkingPotentialConstantExpression()) return false; if (!Info.CurrentCall->This) { + if (Info.AccessingStaticConstantDataMember) { + return Success(E); + } if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); else diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -908,3 +908,17 @@ return testDefaultArgForParam() + testDefaultArgForParam((E)1); } } + +namespace GH56246 { +struct S { + static consteval int hello() { return 1;} + static constexpr int world() { return 1;} + + consteval int baz() const { return this->hello();} + // Previously these two failed because of the use of `this` in the constant expressions. + int foo() const { return this->hello() + this->world(); } + constexpr int bar() const { return this->hello() + this->world();} +} s; +static_assert(s.bar() == 2); +static_assert(s.baz() == 1); +} \ No newline at end of file