Skip to content

Commit ecc12d6

Browse files
cor3ntincompnerd
authored andcommitted
[Clang] Implement CWG2518 - static_assert(false)
This allows `static_assert(false)` to not be ill-formed in template definitions. This change is applied as a DR in all C++ modes. Of notes, a couple of tests were relying of the eager nature of static_assert * test/SemaTemplate/instantiation-dependence.cpp * test/SemaTemplate/instantiate-var-template.cpp I don't know if the changes to `static_assert` still allow that sort of tests to be expressed. Reviewed By: #clang-language-wg, erichkeane, aaron.ballman Differential Revision: https://reviews.llvm.org/D144285 (cherry picked from commit 00e2098)
1 parent fe0f467 commit ecc12d6

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17146,21 +17146,14 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
1714617146
FoldKind).isInvalid())
1714717147
Failed = true;
1714817148

17149-
// If the static_assert passes, only verify that
17150-
// the message is grammatically valid without evaluating it.
17151-
if (!Failed && AssertMessage && Cond.getBoolValue()) {
17152-
std::string Str;
17153-
EvaluateStaticAssertMessageAsString(AssertMessage, Str, Context,
17154-
/*ErrorOnInvalidMessage=*/false);
17155-
}
17156-
1715717149
// CWG2518
1715817150
// [dcl.pre]/p10 If [...] the expression is evaluated in the context of a
1715917151
// template definition, the declaration has no effect.
1716017152
bool InTemplateDefinition =
1716117153
getLangOpts().CPlusPlus && CurContext->isDependentContext();
1716217154

1716317155
if (!Failed && !Cond && !InTemplateDefinition) {
17156+
1716417157
SmallString<256> MsgBuffer;
1716517158
llvm::raw_svector_ostream Msg(MsgBuffer);
1716617159
bool HasMessage = AssertMessage;
@@ -17192,8 +17185,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
1719217185
<< InnerCond->getSourceRange();
1719317186
DiagnoseStaticAssertDetails(InnerCond);
1719417187
} else {
17195-
Diag(AssertExpr->getBeginLoc(), diag::err_static_assert_failed)
17196-
<< !HasMessage << Msg.str() << AssertExpr->getSourceRange();
17188+
Diag(StaticAssertLoc, diag::err_static_assert_failed)
17189+
<< !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
1719717190
PrintContextStack();
1719817191
}
1719917192
Failed = true;

clang/test/CXX/drs/dr25xx.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,40 @@ using ::dr2521::operator""_div;
8181
#endif
8282
} // namespace dr2521
8383

84+
namespace dr2518 { // dr2518: 17 review
85+
86+
template <class T>
87+
void f(T t) {
88+
if constexpr (sizeof(T) != sizeof(int)) {
89+
static_assert(false, "must be int-sized"); // expected-error {{must be int-size}}
90+
}
91+
}
92+
93+
void g(char c) {
94+
f(0);
95+
f(c); // expected-note {{requested here}}
96+
}
97+
98+
template <typename Ty>
99+
struct S {
100+
static_assert(false); // expected-error {{static assertion failed}}
101+
};
102+
103+
template <>
104+
struct S<int> {};
105+
106+
template <>
107+
struct S<float> {};
108+
109+
int test_specialization() {
110+
S<int> s1;
111+
S<float> s2;
112+
S<double> s3; // expected-note {{in instantiation of template class 'dr2518::S<double>' requested here}}
113+
}
114+
115+
}
116+
117+
84118
namespace dr2565 { // dr2565: 16 open
85119
#if __cplusplus >= 202002L
86120
template<typename T>

0 commit comments

Comments
 (0)