Open llvmbot opened 9 years ago
Reconfirmed on trunk with following:
template <typename T>
void dummy() {
static __thread T* ptr(0);
}
I am looking at where this diagnostic is generated:
if (var->getType().isDestructedType()) {
// GNU C++98 edits for __thread, [basic.start.term]p3:
// The type of an object with thread storage duration shall not
// have a non-trivial destructor.
Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
if (getLangOpts().CPlusPlus11)
Diag(var->getLocation(), diag::note_use_thread_local);
} else if (getLangOpts().CPlusPlus && var->hasInit()) {
if (!checkConstInit()) {
// GNU C++98 edits for __thread, [basic.start.init]p4:
// An object of thread storage duration shall not require dynamic
// initialization.
// FIXME: Need strict checking here.
Diag(CacheCulprit->getExprLoc(), diag::err_thread_dynamic_init)
<< CacheCulprit->getSourceRange();
if (getLangOpts().CPlusPlus11)
Diag(var->getLocation(), diag::note_use_thread_local);
}
}
and I think this looks like a bug but I would have do more digging.
CC @zygoloid
We shouldn't be trying to check if a dependent variable/initializer is constant.
Whether this check makes sense at all is a separate issue.
The other calls to checkConstInit
are guarded by:
if (getLangOpts().CPlusPlus && !type->isDependentType() && Init &&
!Init->isValueDependent() &&
... some of which seem to be missing here. The isDestructedType
check for __thread
also should be skipped for a variable with a dependent type, but we seem to get away with that because we seem to treat dependent types as trivially-destructed.
Extended Description
I bumped Clang to pre-3.6 (65d8b4c4998b3a0c20934ea72ede72ef4838a004, r222081, ~15 Nov). Have not checked the trunk version.
The following will work:
The following will not work:
It works with c-like initialization, but not with constructor initialization or uniform initialization.
We are assigning initial value of pointer (
nullptr
), isn'tnullptr
/0
are constant expression here?