This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Fix nesting of discarded and immediate contexts.
ClosedPublic

Authored by cor3ntin on Nov 12 2021, 3:30 AM.

Details

Reviewers
aaron.ballman
Summary

In C++23, discarded statements and if consteval statements can nest
arbitrarily. To support that, we
keep track of whether the parent of the current evaluation context
is discarded or immediate.

This is done at the construction of an evaluation context
to improve performance.

Fixes https://bugs.llvm.org/show_bug.cgi?id=52231

Diff Detail

Event Timeline

cor3ntin requested review of this revision.Nov 12 2021, 3:30 AM
cor3ntin created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptNov 12 2021, 3:30 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
cor3ntin updated this revision to Diff 386783.Nov 12 2021, 3:40 AM

Fix commit message

cor3ntin retitled this revision from [Clang] Fix nesting of discarded an immediate context. to [Clang] Fix nesting of discarded and immediate contexts..Nov 12 2021, 3:40 AM
aaron.ballman added inline comments.Dec 1 2021, 7:27 AM
clang/include/clang/Sema/Sema.h
1300–1301

No real benefit to making these bit-fields, and it'd be good to add some documentation about why the fields exist.

clang/lib/Sema/SemaExpr.cpp
16571–16573
16575–16578

It took me a moment to understand why -2 was happening here. However, isn't this going to be UB when we go to push the first expr evaluation context?

cor3ntin updated this revision to Diff 391030.Dec 1 2021, 7:53 AM
cor3ntin marked an inline comment as done.

Add and fix comments

cor3ntin updated this revision to Diff 391032.Dec 1 2021, 7:56 AM

Remove bitfields

cor3ntin added inline comments.Dec 1 2021, 7:58 AM
clang/lib/Sema/SemaExpr.cpp
16575–16578

No, there is always one root context created during initialization of sema. Because this pattern is used in a few places, I did not add a comment.

aaron.ballman accepted this revision.Dec 1 2021, 8:20 AM

LGTM! Thank you for the fix!

clang/lib/Sema/SemaExpr.cpp
16575–16578

Ah, good to know, thank you!

This revision is now accepted and ready to land.Dec 1 2021, 8:20 AM
aaron.ballman closed this revision.Dec 1 2021, 9:59 AM

I've commit on your behalf in 6eeda06c1d22da2b9fe96a2569a8a0f8e4f36880, thanks!

This change breaks return value deduction of template instantiations that first occur within a discarded context.

template<int S>
class Foo {
public:
	constexpr Foo(const char str[S]) : buf(str[0]) {}
	char get() const { return buf; }
	char buf;
};

template<int S>
static constexpr auto make(const char(&str)[S]) {
	return Foo<S>{str};
}

int main() {
	if constexpr(false) {
		return make("used to be Foo<29>, now void").get();
	}
	return 0;
}

This code now fails to compile with

regression.cpp:16:46: error: member reference base type 'void' is not a structure or union
                return make("used to be Foo<29>, now void").get();
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~

The only return statement in the make() function template is not being considered anymore, making the resulting instantiation

template<>
static constexpr void make(const char(&str)[29]) {
	return Foo<29>{str};
}

Intuitively, I wouldn't think that the "discarded return statements are not considered when deducing a return type" rule should continue into new function scopes, though I'm not sure exactly how the spec backs that up.

This change breaks return value deduction of template instantiations that first occur within a discarded context.

Thank you for letting us know! I think we've fixed this issue in https://reviews.llvm.org/D115228 which was landed in 2334314550724812bb94e36c6b5df7d665bdbd9d. Can you let us know if that does not address your issue?