Skip to content

Commit

Permalink
Properly diagnose constant evaluation issues at TU scope
Browse files Browse the repository at this point in the history
We were not creating an evaluation context for the TU scope, so we
never popped an evaluation context for it. Popping the evaluation
context triggers a number of diagnostics, including warnings about
immediate invocations that we were previously missing.

Note: I think we have an additional issue that we should solve, but not
as part of this patch. I don't think Clang is properly modeling static
initialization as happening before constant expression evaluation. I
think structure members members are zero initialized per
http://eel.is/c++draft/basic.start.static#1,
https://eel.is/c++draft/basic.start.static#2.sentence-2, and
http://eel.is/c++draft/dcl.init#general-6.2 and the new test case
actually should be accepted. However, it's also worth noting that other
compilers behave the way this patch makes Clang behave:
https://godbolt.org/z/T7noqhdPr
  • Loading branch information
AaronBallman committed Mar 8, 2022
1 parent 5b7941a commit 1c55f05
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ C++ Language Changes in Clang

C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- Diagnose consteval and constexpr issues that happen at namespace scope. This
partially addresses `Issue 51593 <https://github.com/llvm/llvm-project/issues/51593>`_.

C++2b Feature Support
^^^^^^^^^^^^^^^^^^^^^
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Parse/ParseAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
P.Initialize();
Parser::DeclGroupPtrTy ADecl;
Sema::ModuleImportState ImportState;
EnterExpressionEvaluationContext PotentiallyEvaluated(
S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
AtEOF = P.ParseTopLevelDecl(ADecl, ImportState)) {
// If we got a null return and something *was* parsed, ignore it. This
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
// Tell diagnostics how to render things from the AST library.
Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);

// This evaluation context exists to ensure that there's always at least one
// valid evaluation context available. It is never removed from the
// evaluation stack.
ExprEvalContexts.emplace_back(
ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
nullptr, ExpressionEvaluationContextRecord::EK_Other);
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,3 +689,23 @@ struct A {
}
};
} // PR48235

namespace NamespaceScopeConsteval {
struct S {
int Val; // expected-note {{subobject declared here}}
consteval S() {}
};

S s1; // expected-error {{call to consteval function 'NamespaceScopeConsteval::S::S' is not a constant expression}} \
expected-note {{subobject of type 'int' is not initialized}}

template <typename Ty>
struct T {
Ty Val; // expected-note {{subobject declared here}}
consteval T() {}
};

T<int> t; // expected-error {{call to consteval function 'NamespaceScopeConsteval::T<int>::T' is not a constant expression}} \
expected-note {{subobject of type 'int' is not initialized}}

} // namespace NamespaceScopeConsteval

0 comments on commit 1c55f05

Please sign in to comment.