-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Open
Labels
clang:frontendLanguage frontend issues, e.g. anything involving "Sema"Language frontend issues, e.g. anything involving "Sema"confirmedVerified by a second partyVerified by a second partylibstdc++GNU libstdc++ C++ standard libraryGNU libstdc++ C++ standard libraryrejects-valid
Description
Not sure how to title this properly.
The original reproducer is just:
#include <string>
constexpr auto z = std::string("", 0);
with libstdc++.
Using cvise, I get:
template <typename _CharT>
struct basic_string {
constexpr void _M_construct();
constexpr basic_string() {
_M_construct();
}
};
basic_string<char *> a;
template <typename _CharT>
constexpr void basic_string<_CharT>::_M_construct(){}
constexpr basic_string<char*> z{};
https://godbolt.org/z/7PzreExcf
Clang's output is:
<source>:18:16: error: constexpr variable 'z' must be initialized by a constant expression
18 | constexpr auto z = basic_string<char *>();
| ^ ~~~~~~~~~~~~~~~~~~~~~~
<source>:6:5: note: undefined function '_M_construct' cannot be used in a constant expression
6 | _M_construct();
| ^
<source>:18:20: note: in call to 'basic_string()'
18 | constexpr basic_string<char*> z{}
| ^~~~~~~~~~~~~~~~~~~~~~
<source>:3:18: note: declared here
3 | constexpr void _M_construct();
| ^
The problem vanishes if a
is commented out, or if basic_string
is not a template anymore.
Metadata
Metadata
Labels
clang:frontendLanguage frontend issues, e.g. anything involving "Sema"Language frontend issues, e.g. anything involving "Sema"confirmedVerified by a second partyVerified by a second partylibstdc++GNU libstdc++ C++ standard libraryGNU libstdc++ C++ standard libraryrejects-valid
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
llvmbot commentedon Nov 23, 2023
@llvm/issue-subscribers-clang-frontend
Author: Timm Baeder (tbaederr)
The original reproducer is just:
with libstdc++.
Using cvise, I get:
https://godbolt.org/z/7PzreExcf
Clang's output is:
The problem vanishes if
operators()
is commented out, or ifbasic_string
is not a template anymore.cor3ntin commentedon Nov 23, 2023
same problem with free functions
cor3ntin commentedon Nov 23, 2023
We probably want to call
Sema::InstantiateFunctionDefinition
inCheckConstexprFunction
.Unfortunately,
CheckConstexprFunction
does not have access toSema
. in general, nothing in ExprConstant has access to Sema.To fix that we'd need to add a reference to Sema in
EvalInfo
, probably. A bit tedious. Anyone has a better idea? @erichkeanetbaederr commentedon Nov 23, 2023
CC @AaronBallman and @zygoloid, maybe they have an idea
zygoloid commentedon Nov 23, 2023
Ultimately this is a language bug. There's no point of instantiation after the function template is defined and before the end of the TU -- we only get PoIs at uses and at end of TU.
What we should probably do is instantiate all used specializations at the point where the function template is defined (if it's constexpr). Constant evaluation shouldn't have side effects.
I'm pretty sure this is a duplicate of a (very) old PR.
zygoloid commentedon Nov 23, 2023
See CWG2497.
cor3ntin commentedon Nov 24, 2023
Hum, I can see how trying to do instantiations in the middle of constant evaluation would not be great, thanks!
Do you think we should wait for core to resolve the issue, or should we try to eagerly instantiate at the end of the definition of constexpr functions?
zygoloid commentedon Nov 25, 2023
I think we should eagerly start instantiating at the end of definitions. (Both function and variable templates are affected by this IIRC.)
10 remaining items
zygoloid commentedon Dec 2, 2023
Normally I'd just say that the code needs to be fixed to give the explicit specialization before it's used or to make sure the instantiation is deferred, but the breakage is probably too much given that this seems to be in Qt core code.
I guess the question is, do we follow GCC's problematic model that evaluation can cause instantiation (which the language rules elsewhere explicitly try to avoid), or do we add a workaround just for Qt (detect that pattern somehow and don't eagerly Instantiate)?
cor3ntin commentedon Dec 3, 2023
It seems like EDG/MSVC follow the same model. I sent a mail to CWG, but i doubt it will help make progress.
cor3ntin commentedon Apr 8, 2024
@zygoloid The current direction taking by the reflection proposal is that arbitrary instantiations can emanate from constexpr evaluation. (Both explicitly as there is a proposed method to instantiate and define classes, and implicitly when querying the properties of not yet instantiated definitions).
In that way the model you consider problematic is going to be mandated by the standard
Is that something you gave any thought above? It might impact how we resolve this issue
zygoloid commentedon Apr 8, 2024
Thinking about the Qt example some more, if you simply reverse the order of the function definitions:
... then the example is clearly invalid (albeit no diagnostic required, because there are two points of instantiation for
fromType<int>
and only one of them results in the use ofQMetaTypeId<int>
prior to the explicit specialization), and clang correctly rejects. (GCC still doesn't, which is also permissible.) It seems pretty hard to justify why this example should be valid with the use and the template definition in the other order. The explicit specialization is simply declared too late.Fedr commentedon Apr 7, 2025
A similar issue presented in https://stackoverflow.com/q/79558008/7325599
GCC, EDG, MSVC all accept it. But Clang complains:
Online demo: https://gcc.godbolt.org/z/xnGEM7oqe
constexpr string
fromconstexpr string_view
is not always a constant expression #142144 as a duplicate of this issue