Stop instantiating a class if we hit a static_assert failure. Also, if the
static_assert fails when parsing the template, don't diagnose it again on every
instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160088 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 11a5260..77e693c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -2005,15 +2005,17 @@
SourceLocation StaticAssertLoc,
Expr *AssertExpr,
StringLiteral *Message,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ bool Failed) {
return new (C) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message,
- RParenLoc);
+ RParenLoc, Failed);
}
StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(StaticAssertDecl));
- return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0,SourceLocation());
+ return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0,
+ SourceLocation(), false);
}
static const char *getAccessName(AccessSpecifier AS) {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index fa42fdd..ebd9180 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -9736,37 +9736,49 @@
Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr,
- Expr *AssertMessageExpr_,
+ Expr *AssertMessageExpr,
SourceLocation RParenLoc) {
- StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_);
+ StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr);
- if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
+ if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
+ return 0;
+
+ return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr,
+ AssertMessage, RParenLoc, false);
+}
+
+Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+ Expr *AssertExpr,
+ StringLiteral *AssertMessage,
+ SourceLocation RParenLoc,
+ bool Failed) {
+ if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() &&
+ !Failed) {
// In a static_assert-declaration, the constant-expression shall be a
// constant expression that can be contextually converted to bool.
ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
if (Converted.isInvalid())
- return 0;
+ Failed = true;
llvm::APSInt Cond;
- if (VerifyIntegerConstantExpression(Converted.get(), &Cond,
+ if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,
diag::err_static_assert_expression_is_not_constant,
/*AllowFold=*/false).isInvalid())
- return 0;
+ Failed = true;
- if (!Cond) {
+ if (!Failed && !Cond) {
llvm::SmallString<256> MsgBuffer;
llvm::raw_svector_ostream Msg(MsgBuffer);
AssertMessage->printPretty(Msg, Context, 0, getPrintingPolicy());
Diag(StaticAssertLoc, diag::err_static_assert_failed)
<< Msg.str() << AssertExpr->getSourceRange();
+ Failed = true;
}
}
- if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
- return 0;
-
Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
- AssertExpr, AssertMessage, RParenLoc);
+ AssertExpr, AssertMessage, RParenLoc,
+ Failed);
CurContext->addDecl(Decl);
return Decl;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 239a0d7..0a0016c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1904,7 +1904,7 @@
continue;
if ((*Member)->isInvalidDecl()) {
- Instantiation->setInvalidDecl();
+ Instantiation->setInvalidDecl();
continue;
}
@@ -1928,6 +1928,13 @@
MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
+ } else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(NewMember)) {
+ if (SA->isFailed()) {
+ // A static_assert failed. Bail out; instantiating this
+ // class is probably not meaningful.
+ Instantiation->setInvalidDecl();
+ break;
+ }
}
if (NewMember->isInvalidDecl())
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index cce0b0d..0d3e8a0 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -552,12 +552,11 @@
if (InstantiatedAssertExpr.isInvalid())
return 0;
- ExprResult Message(D->getMessage());
- D->getMessage();
- return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
+ return SemaRef.BuildStaticAssertDeclaration(D->getLocation(),
InstantiatedAssertExpr.get(),
- Message.get(),
- D->getRParenLoc());
+ D->getMessage(),
+ D->getRParenLoc(),
+ D->isFailed());
}
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index f5f9ba2..25f89ad 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1501,7 +1501,8 @@
void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
VisitDecl(D);
- D->AssertExpr = Reader.ReadExpr(F);
+ D->AssertExprAndFailed.setPointer(Reader.ReadExpr(F));
+ D->AssertExprAndFailed.setInt(Record[Idx++]);
D->Message = cast<StringLiteral>(Reader.ReadExpr(F));
D->RParenLoc = ReadSourceLocation(Record, Idx);
}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 96b6022..21ba4d0 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -1222,6 +1222,7 @@
void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getAssertExpr());
+ Record.push_back(D->isFailed());
Writer.AddStmt(D->getMessage());
Writer.AddSourceLocation(D->getRParenLoc(), Record);
Code = serialization::DECL_STATIC_ASSERT;