[libcxx-commits] [clang] [libcxx] pr branch (PR #94669)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jun 6 12:35:00 PDT 2024
https://github.com/EricWF created https://github.com/llvm/llvm-project/pull/94669
- Add contracts keywords
- Add parsing for pre contracts up to Expr
- add contracts builtin prototypes
- add contracts to FunctionDecl
- propagate contracts up to emit function
- add constexpr contract failure
- add constexpr precontract evaluation
- runtime contract violation flag now
- add post contracts
- switch back to CCEDiag
- use abort instead of terminate
>From ffbe0b21314c9036be0e05ffb0da8e04490fddb8 Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Thu, 30 May 2024 22:03:31 +0200
Subject: [PATCH 01/11] Add contracts keywords
---
clang/include/clang/Basic/LangOptions.def | 1 +
clang/include/clang/Basic/TokenKinds.def | 8 ++++++++
clang/lib/Basic/IdentifierTable.cpp | 5 ++++-
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 4061451b2150a..121e9e9459ca7 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -156,6 +156,7 @@ LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
LANGOPT(Coroutines , 1, 0, "C++20 coroutines")
+LANGOPT(Contracts , 1, 1, "C++2c contracts")
LANGOPT(CoroAlignedAllocation, 1, 0, "prefer Aligned Allocation according to P2014 Option 2")
LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods")
LANGOPT(RelaxedTemplateTemplateArgs, 1, 1, "C++17 relaxed matching of template template arguments")
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index b5a0e9df9f7ae..beef4a993014e 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -40,6 +40,9 @@
#ifndef MODULES_KEYWORD
#define MODULES_KEYWORD(X) KEYWORD(X,KEYMODULES)
#endif
+#ifndef CONTRACTS_KEYWORD
+#define CONTRACTS_KEYWORD(X) KEYWORD(X,KEYCONTRACTS)
+#endif
#ifndef TYPE_TRAIT
#define TYPE_TRAIT(N,I,K) KEYWORD(I,K)
#endif
@@ -280,6 +283,7 @@ PUNCTUATOR(caretcaret, "^^")
// which are heavily based on AltiVec
// KEYBORLAND - This is a keyword if Borland extensions are enabled
// KEYCOROUTINES - This is a keyword if support for C++ coroutines is enabled
+// KEYCONTRACTS - This is a keyword if support for C++ contracts is enabled
// BOOLSUPPORT - This is a keyword if 'bool' is a built-in type
// HALFSUPPORT - This is a keyword if 'half' is a built-in type
// WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type
@@ -415,6 +419,10 @@ CXX20_KEYWORD(constinit , 0)
CXX20_KEYWORD(concept , 0)
CXX20_KEYWORD(requires , 0)
+// C++ contracts keywords
+CONTRACTS_KEYWORD(pre)
+CONTRACTS_KEYWORD(post)
+
// Not a CXX20_KEYWORD because it is disabled by -fno-char8_t.
KEYWORD(char8_t , CHAR8SUPPORT)
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index feea84544d62f..3070bba7c3f93 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -109,7 +109,8 @@ namespace {
KEYCUDA = 0x1000000,
KEYHLSL = 0x2000000,
KEYFIXEDPOINT = 0x4000000,
- KEYMAX = KEYFIXEDPOINT, // The maximum key
+ KEYCONTRACTS = 0x8000000,
+ KEYMAX = KEYCONTRACTS, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
@@ -189,6 +190,8 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
case KEYCOROUTINES:
return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
+ case KEYCONTRACTS:
+ return LangOpts.Contracts ? KS_Enabled : KS_Unknown;
case KEYMODULES:
return KS_Unknown;
case KEYOPENCLCXX:
>From 7fbad4b9b70b6dc8f087c32f6085d1b8229b0b37 Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Thu, 30 May 2024 22:03:50 +0200
Subject: [PATCH 02/11] Add parsing for pre contracts up to Expr
---
clang/include/clang/Parse/Parser.h | 5 ++
clang/include/clang/Sema/DeclSpec.h | 28 ++++++-
clang/lib/Parse/ParseDecl.cpp | 16 ++++
clang/lib/Parse/ParseDeclCXX.cpp | 120 ++++++++++++++++++++++++++++
clang/lib/Parse/ParseExprCXX.cpp | 10 ++-
5 files changed, 177 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index d054b8cf0d240..d01a7bc3fb0b5 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2103,6 +2103,11 @@ class Parser : public CodeCompletionHandler {
ExprResult ParseRequiresExpression();
void ParseTrailingRequiresClause(Declarator &D);
+ //===--------------------------------------------------------------------===//
+ // C++ Contracts
+ void ParsePreContract(Declarator &DeclaratorInfo);
+ void ParsePostContract(Declarator &DeclaratorInfo);
+
//===--------------------------------------------------------------------===//
// C99 6.7.8: Initialization.
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 23bc780e04979..d8c26f69ceab1 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -1970,6 +1970,12 @@ class Declarator {
/// requires-clause, or null if no such clause was specified.
Expr *TrailingRequiresClause;
+ /// \brief All pre contracts specified by the function declaration
+ SmallVector<Expr*> PreContracts;
+
+ /// \brief All post contracts specified by the function declaration
+ SmallVector<Expr*> PostContracts;
+
/// If this declarator declares a template, its template parameter lists.
ArrayRef<TemplateParameterList *> TemplateParameterLists;
@@ -2628,7 +2634,7 @@ class Declarator {
SetRangeEnd(TRC->getEndLoc());
}
-
+
/// \brief Sets a trailing requires clause for this declarator.
Expr *getTrailingRequiresClause() {
return TrailingRequiresClause;
@@ -2640,6 +2646,26 @@ class Declarator {
return TrailingRequiresClause != nullptr;
}
+ /// \brief Add a pre contract for this declarator
+ void addPreContract(Expr *TRC) {
+ PreContracts.push_back(TRC);
+ }
+
+ /// \brief Get all pre contracts for this declarator
+ const SmallVector<Expr*>& getPreContracts() {
+ return PreContracts;
+ }
+
+ /// \brief Add a post contract for this declarator
+ void addPostContract(Expr *TRC) {
+ PostContracts.push_back(TRC);
+ }
+
+ /// \brief Get all post contracts for this declarator
+ const SmallVector<Expr*>& getPostContracts() {
+ return PostContracts;
+ }
+
/// Sets the template parameter lists that preceded the declarator.
void setTemplateParameterLists(ArrayRef<TemplateParameterList *> TPLs) {
TemplateParameterLists = TPLs;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index c528917437332..dabb6ff846a73 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2288,6 +2288,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
if (Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
+ while (Tok.is(tok::kw_pre) || Tok.is(tok::kw_post)) {
+ if (Tok.is(tok::kw_pre)) {
+ ParsePreContract(D);
+ } else {
+ ParsePostContract(D);
+ }
+ }
+
// Save late-parsed attributes for now; they need to be parsed in the
// appropriate function scope after the function Decl has been constructed.
// These will be parsed in ParseFunctionDefinition or ParseLexedAttrList.
@@ -2537,6 +2545,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// init-declarator:
// declarator initializer[opt]
// declarator requires-clause
+ while (Tok.is(tok::kw_pre) || Tok.is(tok::kw_post)) {
+ if (Tok.is(tok::kw_pre)) {
+ ParsePreContract(D);
+ } else {
+ ParsePostContract(D);
+ }
+ }
+
if (Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
Decl *ThisDecl = ParseDeclarationAfterDeclarator(D, TemplateInfo);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 9a4a777f575b2..f9061eb5e2bb9 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2005,6 +2005,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ConsumeBracket();
if (!SkipUntil(tok::r_square, StopAtSemi))
break;
+ } else if ((Tok.is(tok::kw_pre) || Tok.is(tok::kw_post)) && NextToken().is(tok::l_paren)) {
+ ConsumeToken();
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren, StopAtSemi))
+ break;
} else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) {
ConsumeToken();
ConsumeParen();
@@ -2663,6 +2668,14 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
VS);
}
+ while (Tok.is(tok::kw_pre) || Tok.is(tok::kw_post)) {
+ if (Tok.is(tok::kw_pre)) {
+ ParsePreContract(DeclaratorInfo);
+ } else {
+ ParsePostContract(DeclaratorInfo);
+ }
+ }
+
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
SourceLocation Loc;
@@ -4248,6 +4261,113 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
}
+void Parser::ParsePostContract(Declarator &DeclaratorInfo) {
+ ConsumeToken();
+
+ ParseScope ParamScope(this, Scope::DeclScope |
+ Scope::FunctionDeclarationScope |
+ Scope::FunctionPrototypeScope);
+
+ DeclaratorChunk::FunctionTypeInfo FTI = DeclaratorInfo.getFunctionTypeInfo();
+ for (unsigned i = 0; i != FTI.NumParams; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
+ }
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
+ return;
+ }
+ ConsumeParen();
+
+ // Post contracts start with <identifier> colon <expression>
+ // As we have to support the "auto f() post (r : r > 42) {...}" case, we cannot parse here
+ // the return type is not guaranteed to be known until after the function body parses
+
+/*
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
+ return;
+ }
+
+ ParsingDeclSpec DS(*this);
+
+ ParsedTemplateInfo TemplateInfo;
+ DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(DeclaratorContext::Block);
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DSContext);
+
+ ParsedAttributes LocalAttrs(AttrFactory);
+ ParsingDeclarator D(*this, DS, LocalAttrs, DeclaratorContext::Block);
+
+ D.setObjectType(getAsFunction().getReturnType());
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+ D.setIdentifier(Id, IdLoc);
+
+ Decl* ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
+ Actions.ActOnUninitializedDecl(ThisDecl);
+ Actions.FinalizeDeclaration(ThisDecl);
+ D.complete(ThisDecl);
+ if (Tok.isNot(tok::colon)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::colon;
+ return;
+ }
+
+ ExprResult Expr = ParseExpression();
+ if (Expr.isInvalid()) {
+ Diag(Tok.getLocation(), diag::err_invalid_pcs);
+ return;
+ }
+ DeclaratorInfo.addPostContract(Expr.get());
+*/
+ ExprResult Expr = ParseExpression();
+ if (Expr.isInvalid()) {
+ Diag(Tok.getLocation(), diag::err_invalid_pcs);
+ return;
+ }
+ DeclaratorInfo.addPostContract(Expr.get());
+
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ return;
+ }
+ ConsumeParen();
+}
+
+void Parser::ParsePreContract(Declarator &DeclaratorInfo) {
+ ConsumeToken();
+
+ ParseScope ParamScope(this, Scope::DeclScope |
+ Scope::FunctionDeclarationScope |
+ Scope::FunctionPrototypeScope);
+
+ DeclaratorChunk::FunctionTypeInfo FTI = DeclaratorInfo.getFunctionTypeInfo();
+ for (unsigned i = 0; i != FTI.NumParams; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
+ }
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
+ return;
+ }
+ ConsumeParen();
+
+ // Pre contracts are just an expression
+ ExprResult Expr = ParseExpression();
+ if (Expr.isInvalid()) {
+ Diag(Tok.getLocation(), diag::err_invalid_pcs);
+ return;
+ }
+ DeclaratorInfo.addPreContract(Expr.get());
+
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+ return;
+ }
+ ConsumeParen();
+}
+
/// ParseTrailingReturnType - Parse a trailing return type on a new-style
/// function declaration.
TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 1558e3dcb8974..43d3868839de5 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1487,7 +1487,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
tok::kw_constexpr, tok::kw_consteval, tok::kw_static,
tok::kw___private, tok::kw___global, tok::kw___local,
tok::kw___constant, tok::kw___generic, tok::kw_groupshared,
- tok::kw_requires, tok::kw_noexcept) ||
+ tok::kw_requires, tok::kw_pre, tok::kw_post, tok::kw_noexcept) ||
Tok.isRegularKeywordAttribute() ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square));
@@ -1585,6 +1585,14 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
if (HasParentheses && Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
+
+ while (Tok.is(tok::kw_pre) || Tok.is(tok::kw_post)) {
+ if (Tok.is(tok::kw_pre)) {
+ ParsePreContract(D);
+ } else {
+ ParsePostContract(D);
+ }
+ }
}
// Emit a warning if we see a CUDA host/device/global attribute
>From 13ddd08d9040a08ca0cea44aca14eecd876730e9 Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Fri, 31 May 2024 11:49:43 +0200
Subject: [PATCH 03/11] add contracts builtin prototypes
---
clang/include/clang/Basic/Builtins.td | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 11982af3fa609..79a26256bee68 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2575,6 +2575,20 @@ def SetJmpEx : MSLibBuiltin<"setjmpex.h"> {
let Prototype = "int(jmp_buf)";
}
+// C++ contracts
+def ContractViolation : Builtin {
+ let Spellings = ["contract_violation"];
+ let Prototype = "void(char const*, int, char const*)";
+ let Attributes = [NoThrow];
+ let Namespace = "std";
+}
+
+def ContractAssert : Builtin {
+ let Spellings = ["contract_assert"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(bool)";
+}
+
// C99 library functions
// C99 stdarg.h
def VaStart : LibBuiltin<"stdarg.h"> {
>From 165068c64bece75030961915a4da40be3d88aec7 Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Fri, 31 May 2024 13:12:14 +0200
Subject: [PATCH 04/11] add contracts to FunctionDecl
---
clang/include/clang/AST/Decl.h | 20 +++++++++-----
clang/include/clang/AST/DeclCXX.h | 22 ++++++++--------
clang/include/clang/Sema/Sema.h | 2 ++
clang/lib/AST/ASTImporter.cpp | 11 ++++----
clang/lib/AST/Decl.cpp | 7 ++---
clang/lib/AST/DeclCXX.cpp | 26 +++++++++----------
clang/lib/Sema/SemaDecl.cpp | 13 +++++-----
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 ++-
8 files changed, 59 insertions(+), 45 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 7fd80b90d1033..bb885f3ef1a3c 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -769,11 +769,12 @@ struct QualifierInfo {
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
// A struct representing a TInfo, a trailing requires-clause and a syntactic
- // qualifier, to be used for the (uncommon) case of out-of-line declarations
- // and constrained function decls.
+ // qualifier, to be used for the (uncommon) case of out-of-line declarations,
+ // constrained function decls or functions with contracts.
struct ExtInfo : public QualifierInfo {
TypeSourceInfo *TInfo;
Expr *TrailingRequiresClause = nullptr;
+ SmallVector<Expr*> PreContracts = {};
};
llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
@@ -853,8 +854,15 @@ class DeclaratorDecl : public ValueDecl {
: nullptr;
}
+ SmallVector<Expr*> getPreContracts() const {
+ if (hasExtInfo()) return getExtInfo()->PreContracts;
+ return {};
+ }
+
void setTrailingRequiresClause(Expr *TrailingRequiresClause);
+ void setPreContracts(SmallVector<Expr*> PreContracts);
+
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
@@ -2126,7 +2134,7 @@ class FunctionDecl : public DeclaratorDecl,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin,
bool isInlineSpecified, ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause = nullptr);
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
using redeclarable_base = Redeclarable<FunctionDecl>;
@@ -2162,12 +2170,12 @@ class FunctionDecl : public DeclaratorDecl,
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin = false,
bool isInlineSpecified = false, bool hasWrittenPrototype = true,
ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified,
- Expr *TrailingRequiresClause = nullptr) {
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {}) {
DeclarationNameInfo NameInfo(N, NLoc);
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC,
UsesFPIntrin, isInlineSpecified,
hasWrittenPrototype, ConstexprKind,
- TrailingRequiresClause);
+ TrailingRequiresClause, PreContracts);
}
static FunctionDecl *
@@ -2175,7 +2183,7 @@ class FunctionDecl : public DeclaratorDecl,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified,
bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause);
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts);
static FunctionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index fb52ac804849d..4b7689266c36e 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2066,9 +2066,9 @@ class CXXMethodDecl : public FunctionDecl {
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
bool UsesFPIntrin, bool isInline,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr)
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {})
: FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
- isInline, ConstexprKind, TrailingRequiresClause) {
+ isInline, ConstexprKind, TrailingRequiresClause, PreContracts) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
}
@@ -2079,7 +2079,7 @@ class CXXMethodDecl : public FunctionDecl {
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
StorageClass SC, bool UsesFPIntrin, bool isInline,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr);
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
static CXXMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
@@ -2547,7 +2547,7 @@ class CXXConstructorDecl final
bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
InheritedConstructor Inherited,
- Expr *TrailingRequiresClause);
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts);
void anchor() override;
@@ -2590,7 +2590,7 @@ class CXXConstructorDecl final
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
InheritedConstructor Inherited = InheritedConstructor(),
- Expr *TrailingRequiresClause = nullptr);
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
void setExplicitSpecifier(ExplicitSpecifier ES) {
assert((!ES.getExpr() ||
@@ -2809,10 +2809,10 @@ class CXXDestructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause = nullptr)
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {})
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, UsesFPIntrin, isInline, ConstexprKind,
- SourceLocation(), TrailingRequiresClause) {
+ SourceLocation(), TrailingRequiresClause, PreContracts) {
setImplicit(isImplicitlyDeclared);
}
@@ -2824,7 +2824,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause = nullptr);
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
@@ -2865,10 +2865,10 @@ class CXXConversionDecl : public CXXMethodDecl {
TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline,
ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind,
SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr)
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {})
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, UsesFPIntrin, isInline, ConstexprKind,
- EndLocation, TrailingRequiresClause),
+ EndLocation, TrailingRequiresClause, PreContracts),
ExplicitSpec(ES) {}
void anchor() override;
@@ -2883,7 +2883,7 @@ class CXXConversionDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr);
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
static CXXConversionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ExplicitSpecifier getExplicitSpecifier() {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7dea2b6826cfd..ba43236aa46b9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4765,6 +4765,8 @@ class Sema final : public SemaBase {
void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
+ void ActOnPreContract(Scope *S, Declarator &D);
+ void ActOnPostContract(Scope *S, Declarator &D);
NamedDecl *
ActOnDecompositionDeclarator(Scope *S, Declarator &D,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index cab5ee6047956..ab132d6449813 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3857,6 +3857,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
auto TrailingRequiresClause =
importChecked(Err, D->getTrailingRequiresClause());
+ auto PreContracts = D->getPreContracts();
if (Err)
return std::move(Err);
@@ -3888,7 +3889,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->UsesFPIntrin(),
D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
- ToInheritedConstructor, TrailingRequiresClause))
+ ToInheritedConstructor, TrailingRequiresClause, PreContracts))
return ToFunction;
} else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {
@@ -3903,7 +3904,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(),
D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
- TrailingRequiresClause))
+ TrailingRequiresClause, PreContracts))
return ToFunction;
CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction);
@@ -3919,14 +3920,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(),
D->isInlineSpecified(), ESpec, D->getConstexprKind(),
- SourceLocation(), TrailingRequiresClause))
+ SourceLocation(), TrailingRequiresClause, PreContracts))
return ToFunction;
} else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (GetImportedOrCreateDecl<CXXMethodDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(),
Method->UsesFPIntrin(), Method->isInlineSpecified(),
- D->getConstexprKind(), SourceLocation(), TrailingRequiresClause))
+ D->getConstexprKind(), SourceLocation(), TrailingRequiresClause, PreContracts))
return ToFunction;
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
ExplicitSpecifier ESpec =
@@ -3946,7 +3947,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
NameInfo, T, TInfo, D->getStorageClass(), D->UsesFPIntrin(),
D->isInlineSpecified(), D->hasWrittenPrototype(),
- D->getConstexprKind(), TrailingRequiresClause))
+ D->getConstexprKind(), TrailingRequiresClause, PreContracts))
return ToFunction;
}
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 0a35ed536a6a7..b174201b61803 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3042,7 +3042,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
TypeSourceInfo *TInfo, StorageClass S,
bool UsesFPIntrin, bool isInlineSpecified,
ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause)
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
StartLoc),
DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
@@ -3078,6 +3078,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
if (TrailingRequiresClause)
setTrailingRequiresClause(TrailingRequiresClause);
+// setPreContracts(PreContracts);
}
void FunctionDecl::getNameForDiagnostic(
@@ -5401,10 +5402,10 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
bool isInlineSpecified, bool hasWrittenPrototype,
ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause) {
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
FunctionDecl *New = new (C, DC) FunctionDecl(
Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
- isInlineSpecified, ConstexprKind, TrailingRequiresClause);
+ isInlineSpecified, ConstexprKind, TrailingRequiresClause, PreContracts);
New->setHasWrittenPrototype(hasWrittenPrototype);
return New;
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 75c441293d62e..c7cf36bed83c6 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2276,10 +2276,10 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
bool isInline, ConstexprSpecKind ConstexprKind,
SourceLocation EndLocation,
- Expr *TrailingRequiresClause) {
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
return new (C, RD) CXXMethodDecl(
CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
- isInline, ConstexprKind, EndLocation, TrailingRequiresClause);
+ isInline, ConstexprKind, EndLocation, TrailingRequiresClause, PreContracts);
}
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C,
@@ -2287,7 +2287,7 @@ CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C,
return new (C, ID) CXXMethodDecl(
CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
QualType(), nullptr, SC_None, false, false,
- ConstexprSpecKind::Unspecified, SourceLocation(), nullptr);
+ ConstexprSpecKind::Unspecified, SourceLocation(), nullptr, {});
}
CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
@@ -2685,10 +2685,10 @@ CXXConstructorDecl::CXXConstructorDecl(
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
- InheritedConstructor Inherited, Expr *TrailingRequiresClause)
+ InheritedConstructor Inherited, Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts)
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, UsesFPIntrin, isInline, ConstexprKind,
- SourceLocation(), TrailingRequiresClause) {
+ SourceLocation(), TrailingRequiresClause, PreContracts) {
setNumCtorInitializers(0);
setInheritingConstructor(static_cast<bool>(Inherited));
setImplicit(isImplicitlyDeclared);
@@ -2712,7 +2712,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
ExplicitSpecifier(), false, false, false, ConstexprSpecKind::Unspecified,
- InheritedConstructor(), nullptr);
+ InheritedConstructor(), nullptr, {});
Result->setInheritingConstructor(isInheritingConstructor);
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
hasTrailingExplicit;
@@ -2725,7 +2725,7 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
- InheritedConstructor Inherited, Expr *TrailingRequiresClause) {
+ InheritedConstructor Inherited, Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
@@ -2734,7 +2734,7 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
Inherited ? 1 : 0, ES.getExpr() ? 1 : 0);
return new (C, RD, Extra) CXXConstructorDecl(
C, RD, StartLoc, NameInfo, T, TInfo, ES, UsesFPIntrin, isInline,
- isImplicitlyDeclared, ConstexprKind, Inherited, TrailingRequiresClause);
+ isImplicitlyDeclared, ConstexprKind, Inherited, TrailingRequiresClause, PreContracts);
}
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
@@ -2851,20 +2851,20 @@ CXXDestructorDecl *CXXDestructorDecl::CreateDeserialized(ASTContext &C,
GlobalDeclID ID) {
return new (C, ID) CXXDestructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
- false, false, false, ConstexprSpecKind::Unspecified, nullptr);
+ false, false, false, ConstexprSpecKind::Unspecified, nullptr, {});
}
CXXDestructorDecl *CXXDestructorDecl::Create(
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
- ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) {
+ ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXDestructorName &&
"Name must refer to a destructor");
return new (C, RD) CXXDestructorDecl(
C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline,
- isImplicitlyDeclared, ConstexprKind, TrailingRequiresClause);
+ isImplicitlyDeclared, ConstexprKind, TrailingRequiresClause, PreContracts);
}
void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
@@ -2892,13 +2892,13 @@ CXXConversionDecl *CXXConversionDecl::Create(
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause) {
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConversionFunctionName &&
"Name must refer to a conversion function");
return new (C, RD) CXXConversionDecl(
C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline, ES,
- ConstexprKind, EndLocation, TrailingRequiresClause);
+ ConstexprKind, EndLocation, TrailingRequiresClause, PreContracts);
}
bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 34e46e12859bb..1853ac81ca829 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9325,7 +9325,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
SemaRef.getCurFPFeatures().isFPConstrained(), isInline, HasPrototype,
ConstexprSpecKind::Unspecified,
- /*TrailingRequiresClause=*/nullptr);
+ /*TrailingRequiresClause=*/nullptr, {});
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -9334,6 +9334,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
Expr *TrailingRequiresClause = D.getTrailingRequiresClause();
+ SmallVector<Expr*> PreContracts = D.getPreContracts();
SemaRef.CheckExplicitObjectMemberFunction(DC, D, Name, R);
@@ -9347,7 +9348,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
TInfo, ExplicitSpecifier, SemaRef.getCurFPFeatures().isFPConstrained(),
isInline, /*isImplicitlyDeclared=*/false, ConstexprKind,
- InheritedConstructor(), TrailingRequiresClause);
+ InheritedConstructor(), TrailingRequiresClause, PreContracts);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
@@ -9382,7 +9383,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return FunctionDecl::Create(
SemaRef.Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), Name, R,
TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
- /*hasPrototype=*/true, ConstexprKind, TrailingRequiresClause);
+ /*hasPrototype=*/true, ConstexprKind, TrailingRequiresClause, PreContracts);
}
} else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
@@ -9401,7 +9402,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
TInfo, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
ExplicitSpecifier, ConstexprKind, SourceLocation(),
- TrailingRequiresClause);
+ TrailingRequiresClause, PreContracts);
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
if (TrailingRequiresClause)
@@ -9430,7 +9431,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
CXXMethodDecl *Ret = CXXMethodDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
- ConstexprKind, SourceLocation(), TrailingRequiresClause);
+ ConstexprKind, SourceLocation(), TrailingRequiresClause, PreContracts);
IsVirtualOkay = !Ret->isStatic();
return Ret;
} else {
@@ -9445,7 +9446,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return FunctionDecl::Create(
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
- true /*HasPrototype*/, ConstexprKind, TrailingRequiresClause);
+ true /*HasPrototype*/, ConstexprKind, TrailingRequiresClause, PreContracts);
}
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4c8eaf2d4ebf6..435223cc50b92 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2163,6 +2163,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
}
Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
+ SmallVector<Expr*> PreContracts = D->getPreContracts();
// If we're instantiating a local function declaration, put the result
// in the enclosing namespace; otherwise we need to find the instantiated
@@ -2200,7 +2201,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
D->getCanonicalDecl()->getStorageClass(), D->UsesFPIntrin(),
D->isInlineSpecified(), D->hasWrittenPrototype(), D->getConstexprKind(),
- TrailingRequiresClause);
+ TrailingRequiresClause, PreContracts);
Function->setFriendConstraintRefersToEnclosingTemplate(
D->FriendConstraintRefersToEnclosingTemplate());
Function->setRangeEnd(D->getSourceRange().getEnd());
>From 87a3f7e1f1c88bef5c59ace6588003f01464345b Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Sun, 2 Jun 2024 13:41:07 +0200
Subject: [PATCH 05/11] propagate contracts up to emit function
---
clang/lib/AST/Decl.cpp | 16 +++++++-
clang/lib/CodeGen/CGBuiltin.cpp | 5 +++
clang/lib/CodeGen/CodeGenFunction.cpp | 53 +++++++++++++++++++++++++++
clang/lib/CodeGen/CodeGenFunction.h | 3 ++
4 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index b174201b61803..5f4c4938f5f41 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2028,6 +2028,20 @@ void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
}
+void DeclaratorDecl::setPreContracts(SmallVector<Expr*> PreContracts) {
+ // Make sure the extended decl info is allocated.
+ if (!hasExtInfo()) {
+ // Save (non-extended) type source info pointer.
+ auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+ // Allocate external info struct.
+ DeclInfo = new (getASTContext()) ExtInfo;
+ // Restore savedTInfo into (extended) decl info.
+ getExtInfo()->TInfo = savedTInfo;
+ }
+ // Set requires clause info.
+ getExtInfo()->PreContracts = PreContracts;
+}
+
void DeclaratorDecl::setTemplateParameterListsInfo(
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
assert(!TPLists.empty());
@@ -3078,7 +3092,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
if (TrailingRequiresClause)
setTrailingRequiresClause(TrailingRequiresClause);
-// setPreContracts(PreContracts);
+ setPreContracts(PreContracts);
}
void FunctionDecl::getNameForDiagnostic(
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 37d0c478e0330..4e4395ba5d96e 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3350,6 +3350,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.CreateCall(FnAssume, ArgValue);
return RValue::get(nullptr);
}
+ case Builtin::BIcontract_assert: {
+ EmitCXXContractCheck(E->getArg(0));
+ EmitCXXContractImply(E->getArg(0));
+ return RValue::get(nullptr);
+ }
case Builtin::BI__builtin_assume_separate_storage: {
const Expr *Arg0 = E->getArg(0);
const Expr *Arg1 = E->getArg(1);
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index f0345f3b191b8..a2592fbb7307f 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -336,6 +336,48 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
return llvm::DebugLoc();
}
+void CodeGenFunction::EmitCXXContractCheck(const Expr* Expr) {
+ llvm::Value *ArgValue = EmitScalarExpr(Expr);
+/*
+ llvm::BasicBlock *Begin = Builder.GetInsertBlock();
+ llvm::BasicBlock *End = createBasicBlock("contract_assert_end", this->CurFn);
+ llvm::BasicBlock *Violation = createBasicBlock("contract_assert_violation", this->CurFn);
+
+ Builder.SetInsertPoint(Begin);
+ Builder.CreateCondBr(ArgValue, End, Violation);
+
+ Builder.SetInsertPoint(Violation);
+ */
+/*
+ SourceRange range = Expr->getSourceRange();
+ PresumedLoc PLoc = Ctx.getSourceManager().getPresumedLoc(range->getBegin());
+ clang::StringLiteral* Filename = PLoc->getFilename();
+ llvm::Value* LineNo = PLoc->getLine();
+ clang::StringLiteral* ExpressionText = range.print(os, Ctx.getSourceManager());
+*/
+ const char *VLibCallName = "__contract_violation"; // const char*
+ CallArgList Args;
+ /*
+ Args.add(EmitLoadOfLValue(EmitStringLiteralLValue(Filename), Expr->getExprLoc()), getContext().VoidPtrTy);
+ Args.add(RValue::get(LineNo), getContext().getSizeType());
+ Args.add(EmitLoadOfLValue(EmitStringLiteralLValue(ExpressionText), Expr->getExprLoc()), getContext().VoidPtrTy);
+ */
+ /*
+ const CGFunctionInfo &VFuncInfo = CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidPtrTy, {});
+ llvm::FunctionType *VFTy = CGM.getTypes().GetFunctionType(VFuncInfo);
+ llvm::FunctionCallee VFunc = CGM.CreateRuntimeFunction(VFTy, VLibCallName);
+ EmitCall(VFuncInfo, CGCallee::forDirect(VFunc), ReturnValueSlot(), Args);
+*/
+
+// Builder.SetInsertPoint(End);
+}
+
+void CodeGenFunction::EmitCXXContractImply(const Expr* expr) {
+ llvm::Value *ArgValue = EmitScalarExpr(expr);
+ llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
+ Builder.CreateCall(FnAssume, ArgValue);
+}
+
static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
if (!BB) return;
if (!BB->use_empty()) {
@@ -420,6 +462,12 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// Emit debug descriptor for function end.
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitFunctionEnd(Builder, CurFn);
+/*
+ for (Expr* expr : FN->getPostContracts()) {
+ EmitCXXContractCheck(expr);
+ EmitCXXContractImply(expr);
+ }
+ */
// Reset the debug location to that of the simple 'return' expression, if any
// rather than that of the end of the function's scope '}'.
@@ -1200,6 +1248,11 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
+ for (Expr* expr : FD->getPreContracts()) {
+ EmitCXXContractCheck(expr);
+ EmitCXXContractImply(expr);
+ }
+
if (const CXXMethodDecl *MD = dyn_cast_if_present<CXXMethodDecl>(D);
MD && !MD->isStatic()) {
bool IsInLambda =
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 45585361a4fc9..fb478929cbb2f 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4337,6 +4337,9 @@ class CodeGenFunction : public CodeGenTypeCache {
LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
void EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init);
+ void EmitCXXContractCheck(const Expr* expr);
+ void EmitCXXContractImply(const Expr* expr);
+
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
>From 1c11146110254428d77a494df6680cda0c617e83 Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Mon, 3 Jun 2024 08:37:16 +0200
Subject: [PATCH 06/11] add constexpr contract failure
---
clang/include/clang/Basic/Builtins.td | 5 +++--
clang/include/clang/Basic/DiagnosticASTKinds.td | 2 ++
clang/lib/AST/ExprConstant.cpp | 11 +++++++++++
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 79a26256bee68..e9ec87a15467f 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2579,13 +2579,14 @@ def SetJmpEx : MSLibBuiltin<"setjmpex.h"> {
def ContractViolation : Builtin {
let Spellings = ["contract_violation"];
let Prototype = "void(char const*, int, char const*)";
- let Attributes = [NoThrow];
+ let Attributes = [NoThrow, Constexpr];
let Namespace = "std";
}
def ContractAssert : Builtin {
let Spellings = ["contract_assert"];
- let Attributes = [NoThrow];
+ let Attributes = [NoThrow, Constexpr];
+
let Prototype = "void(bool)";
}
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index a024f9b2a9f8c..82325f2b396e3 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -403,6 +403,8 @@ def note_constexpr_assumption_failed : Note<
"assumption evaluated to false">;
def err_experimental_clang_interp_failed : Error<
"the experimental clang interpreter failed to evaluate an expression">;
+def note_constexpr_contract_failure : Error<
+ "contract failed during execution of constexpr function">;
def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f1aa19e4409e1..7d5633092447e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15508,6 +15508,17 @@ class VoidExprEvaluator
case Builtin::BI__builtin_operator_delete:
return HandleOperatorDeleteCall(Info, E);
+ case Builtin::BIcontract_assert:
+ {
+ APSInt Desired;
+ if (!EvaluateInteger(E->getArg(0), Desired, Info)){
+ return false;
+ }
+ if (!Desired) {
+ Info.CCEDiag(E, diag::note_constexpr_contract_failure);
+ }
+ return true;
+ }
default:
return false;
}
>From fcd97445f8023e81abb81a277a3b790dc7b69ecd Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Mon, 3 Jun 2024 09:37:08 +0200
Subject: [PATCH 07/11] add constexpr precontract evaluation
---
clang/lib/AST/ExprConstant.cpp | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7d5633092447e..b8ec7eab44efd 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6294,6 +6294,19 @@ static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param,
CopyObjectRepresentation);
}
+static bool EvaluatePreContracts(const FunctionDecl* Callee, EvalInfo& Info) {
+ for (Expr* E : Callee->getPreContracts()) {
+ APSInt Desired;
+ if (!EvaluateInteger(E, Desired, Info)){
+ return false;
+ }
+ if (!Desired) {
+ Info.CCEDiag(E, diag::note_constexpr_contract_failure);
+ }
+ }
+ return true;
+}
+
/// Evaluate a function call.
static bool HandleFunctionCall(SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
@@ -6339,6 +6352,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
Frame.LambdaThisCaptureField);
}
+ EvaluatePreContracts(Callee, Info);
StmtResult Ret = {Result, ResultSlot};
EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body);
if (ESR == ESR_Succeeded) {
@@ -15515,7 +15529,7 @@ class VoidExprEvaluator
return false;
}
if (!Desired) {
- Info.CCEDiag(E, diag::note_constexpr_contract_failure);
+ Info.CCEDiag(E->getArg(0), diag::note_constexpr_contract_failure);
}
return true;
}
>From 59bbcbe9b7d409290515020024b40c59ee4c8ca3 Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Mon, 3 Jun 2024 12:16:50 +0200
Subject: [PATCH 08/11] runtime contract violation flag now
---
clang/include/clang/Basic/Builtins.td | 5 +++--
clang/lib/CodeGen/CodeGenFunction.cpp | 21 ++++++++++++---------
libcxx/src/system_error.cpp | 4 ++++
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index e9ec87a15467f..88bb52af92521 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2578,8 +2578,9 @@ def SetJmpEx : MSLibBuiltin<"setjmpex.h"> {
// C++ contracts
def ContractViolation : Builtin {
let Spellings = ["contract_violation"];
- let Prototype = "void(char const*, int, char const*)";
- let Attributes = [NoThrow, Constexpr];
+// let Prototype = "void(char const*, int, char const*)";
+ let Prototype = "void()";
+ let Attributes = [NoThrow, NoReturn, Constexpr];
let Namespace = "std";
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a2592fbb7307f..22665ec4b34f7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -338,7 +338,6 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
void CodeGenFunction::EmitCXXContractCheck(const Expr* Expr) {
llvm::Value *ArgValue = EmitScalarExpr(Expr);
-/*
llvm::BasicBlock *Begin = Builder.GetInsertBlock();
llvm::BasicBlock *End = createBasicBlock("contract_assert_end", this->CurFn);
llvm::BasicBlock *Violation = createBasicBlock("contract_assert_violation", this->CurFn);
@@ -347,7 +346,7 @@ void CodeGenFunction::EmitCXXContractCheck(const Expr* Expr) {
Builder.CreateCondBr(ArgValue, End, Violation);
Builder.SetInsertPoint(Violation);
- */
+
/*
SourceRange range = Expr->getSourceRange();
PresumedLoc PLoc = Ctx.getSourceManager().getPresumedLoc(range->getBegin());
@@ -355,21 +354,25 @@ void CodeGenFunction::EmitCXXContractCheck(const Expr* Expr) {
llvm::Value* LineNo = PLoc->getLine();
clang::StringLiteral* ExpressionText = range.print(os, Ctx.getSourceManager());
*/
- const char *VLibCallName = "__contract_violation"; // const char*
+ const char *VLibCallName = "_ZSt18contract_violationv"; // const char*
CallArgList Args;
- /*
+/*
Args.add(EmitLoadOfLValue(EmitStringLiteralLValue(Filename), Expr->getExprLoc()), getContext().VoidPtrTy);
Args.add(RValue::get(LineNo), getContext().getSizeType());
Args.add(EmitLoadOfLValue(EmitStringLiteralLValue(ExpressionText), Expr->getExprLoc()), getContext().VoidPtrTy);
- */
- /*
- const CGFunctionInfo &VFuncInfo = CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidPtrTy, {});
+*/
+ const CGFunctionInfo &VFuncInfo = CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, {});
llvm::FunctionType *VFTy = CGM.getTypes().GetFunctionType(VFuncInfo);
llvm::FunctionCallee VFunc = CGM.CreateRuntimeFunction(VFTy, VLibCallName);
EmitCall(VFuncInfo, CGCallee::forDirect(VFunc), ReturnValueSlot(), Args);
-*/
-// Builder.SetInsertPoint(End);
+ llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+
+ Builder.SetInsertPoint(End);
}
void CodeGenFunction::EmitCXXContractImply(const Expr* expr) {
diff --git a/libcxx/src/system_error.cpp b/libcxx/src/system_error.cpp
index f518b480a2782..de64edf199278 100644
--- a/libcxx/src/system_error.cpp
+++ b/libcxx/src/system_error.cpp
@@ -220,4 +220,8 @@ void __throw_system_error(int ev, const char* what_arg) {
#endif
}
+void contract_violation() {
+ std::terminate();
+}
+
_LIBCPP_END_NAMESPACE_STD
>From c206da08714efcc6ed22e2ad53c9a39366e3aa2f Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Mon, 3 Jun 2024 19:59:26 +0200
Subject: [PATCH 09/11] add post contracts
---
clang/include/clang/AST/Decl.h | 19 +++++++++---
clang/include/clang/AST/DeclCXX.h | 28 +++++++++++-------
clang/include/clang/Basic/Builtins.td | 3 +-
clang/include/clang/Sema/Sema.h | 2 --
clang/lib/AST/ASTImporter.cpp | 11 +++----
clang/lib/AST/Decl.cpp | 23 +++++++++++++--
clang/lib/AST/DeclCXX.cpp | 29 +++++++++++--------
clang/lib/AST/ExprConstant.cpp | 18 ++++++++++--
clang/lib/CodeGen/CodeGenFunction.cpp | 21 +++++++-------
clang/lib/Sema/SemaDecl.cpp | 13 +++++----
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +-
11 files changed, 111 insertions(+), 59 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index bb885f3ef1a3c..db8786c19452f 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -775,6 +775,7 @@ class DeclaratorDecl : public ValueDecl {
TypeSourceInfo *TInfo;
Expr *TrailingRequiresClause = nullptr;
SmallVector<Expr*> PreContracts = {};
+ SmallVector<Expr*> PostContracts = {};
};
llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
@@ -859,10 +860,17 @@ class DeclaratorDecl : public ValueDecl {
return {};
}
+ SmallVector<Expr*> getPostContracts() const {
+ if (hasExtInfo()) return getExtInfo()->PostContracts;
+ return {};
+ }
+
void setTrailingRequiresClause(Expr *TrailingRequiresClause);
void setPreContracts(SmallVector<Expr*> PreContracts);
+ void setPostContracts(SmallVector<Expr*> PostContracts);
+
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
@@ -2134,7 +2142,8 @@ class FunctionDecl : public DeclaratorDecl,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin,
bool isInlineSpecified, ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {});
using redeclarable_base = Redeclarable<FunctionDecl>;
@@ -2170,12 +2179,13 @@ class FunctionDecl : public DeclaratorDecl,
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin = false,
bool isInlineSpecified = false, bool hasWrittenPrototype = true,
ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {}) {
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {}) {
DeclarationNameInfo NameInfo(N, NLoc);
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC,
UsesFPIntrin, isInlineSpecified,
hasWrittenPrototype, ConstexprKind,
- TrailingRequiresClause, PreContracts);
+ TrailingRequiresClause, PreContracts, PostContracts);
}
static FunctionDecl *
@@ -2183,7 +2193,8 @@ class FunctionDecl : public DeclaratorDecl,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified,
bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts);
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts,
+ SmallVector<Expr*> PostContracts);
static FunctionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 4b7689266c36e..80082b4c49b93 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2066,9 +2066,10 @@ class CXXMethodDecl : public FunctionDecl {
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
bool UsesFPIntrin, bool isInline,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {})
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {})
: FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
- isInline, ConstexprKind, TrailingRequiresClause, PreContracts) {
+ isInline, ConstexprKind, TrailingRequiresClause, PreContracts, PostContracts) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
}
@@ -2079,7 +2080,7 @@ class CXXMethodDecl : public FunctionDecl {
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
StorageClass SC, bool UsesFPIntrin, bool isInline,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {}, SmallVector<Expr*> PostContracts = {});
static CXXMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
@@ -2547,7 +2548,7 @@ class CXXConstructorDecl final
bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
InheritedConstructor Inherited,
- Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts);
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts, SmallVector<Expr*> PostContracts);
void anchor() override;
@@ -2590,7 +2591,8 @@ class CXXConstructorDecl final
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
InheritedConstructor Inherited = InheritedConstructor(),
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {});
void setExplicitSpecifier(ExplicitSpecifier ES) {
assert((!ES.getExpr() ||
@@ -2809,10 +2811,11 @@ class CXXDestructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {})
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {})
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, UsesFPIntrin, isInline, ConstexprKind,
- SourceLocation(), TrailingRequiresClause, PreContracts) {
+ SourceLocation(), TrailingRequiresClause, PreContracts, PostContracts) {
setImplicit(isImplicitlyDeclared);
}
@@ -2824,7 +2827,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {});
static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
@@ -2865,10 +2869,11 @@ class CXXConversionDecl : public CXXMethodDecl {
TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline,
ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind,
SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {})
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {})
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, UsesFPIntrin, isInline, ConstexprKind,
- EndLocation, TrailingRequiresClause, PreContracts),
+ EndLocation, TrailingRequiresClause, PreContracts, PostContracts),
ExplicitSpec(ES) {}
void anchor() override;
@@ -2883,7 +2888,8 @@ class CXXConversionDecl : public CXXMethodDecl {
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {});
+ Expr *TrailingRequiresClause = nullptr, SmallVector<Expr*> PreContracts = {},
+ SmallVector<Expr*> PostContracts = {});
static CXXConversionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ExplicitSpecifier getExplicitSpecifier() {
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 88bb52af92521..6150d3d7a1fb0 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2578,8 +2578,7 @@ def SetJmpEx : MSLibBuiltin<"setjmpex.h"> {
// C++ contracts
def ContractViolation : Builtin {
let Spellings = ["contract_violation"];
-// let Prototype = "void(char const*, int, char const*)";
- let Prototype = "void()";
+ let Prototype = "void(char const*, int, char const*)";
let Attributes = [NoThrow, NoReturn, Constexpr];
let Namespace = "std";
}
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ba43236aa46b9..7dea2b6826cfd 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4765,8 +4765,6 @@ class Sema final : public SemaBase {
void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
- void ActOnPreContract(Scope *S, Declarator &D);
- void ActOnPostContract(Scope *S, Declarator &D);
NamedDecl *
ActOnDecompositionDeclarator(Scope *S, Declarator &D,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index ab132d6449813..58ec48c1c80f8 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3858,6 +3858,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
auto TrailingRequiresClause =
importChecked(Err, D->getTrailingRequiresClause());
auto PreContracts = D->getPreContracts();
+ auto PostContracts = D->getPostContracts();
if (Err)
return std::move(Err);
@@ -3889,7 +3890,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->UsesFPIntrin(),
D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
- ToInheritedConstructor, TrailingRequiresClause, PreContracts))
+ ToInheritedConstructor, TrailingRequiresClause, PreContracts, PostContracts))
return ToFunction;
} else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {
@@ -3904,7 +3905,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(),
D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
- TrailingRequiresClause, PreContracts))
+ TrailingRequiresClause, PreContracts, PostContracts))
return ToFunction;
CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction);
@@ -3920,14 +3921,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(),
D->isInlineSpecified(), ESpec, D->getConstexprKind(),
- SourceLocation(), TrailingRequiresClause, PreContracts))
+ SourceLocation(), TrailingRequiresClause, PreContracts, PostContracts))
return ToFunction;
} else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (GetImportedOrCreateDecl<CXXMethodDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(),
Method->UsesFPIntrin(), Method->isInlineSpecified(),
- D->getConstexprKind(), SourceLocation(), TrailingRequiresClause, PreContracts))
+ D->getConstexprKind(), SourceLocation(), TrailingRequiresClause, PreContracts, PostContracts))
return ToFunction;
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
ExplicitSpecifier ESpec =
@@ -3947,7 +3948,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
NameInfo, T, TInfo, D->getStorageClass(), D->UsesFPIntrin(),
D->isInlineSpecified(), D->hasWrittenPrototype(),
- D->getConstexprKind(), TrailingRequiresClause, PreContracts))
+ D->getConstexprKind(), TrailingRequiresClause, PreContracts, PostContracts))
return ToFunction;
}
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 5f4c4938f5f41..6d2486a3a7927 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2042,6 +2042,20 @@ void DeclaratorDecl::setPreContracts(SmallVector<Expr*> PreContracts) {
getExtInfo()->PreContracts = PreContracts;
}
+void DeclaratorDecl::setPostContracts(SmallVector<Expr*> PostContracts) {
+ // Make sure the extended decl info is allocated.
+ if (!hasExtInfo()) {
+ // Save (non-extended) type source info pointer.
+ auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+ // Allocate external info struct.
+ DeclInfo = new (getASTContext()) ExtInfo;
+ // Restore savedTInfo into (extended) decl info.
+ getExtInfo()->TInfo = savedTInfo;
+ }
+ // Set requires clause info.
+ getExtInfo()->PostContracts = PostContracts;
+}
+
void DeclaratorDecl::setTemplateParameterListsInfo(
ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
assert(!TPLists.empty());
@@ -3056,7 +3070,8 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
TypeSourceInfo *TInfo, StorageClass S,
bool UsesFPIntrin, bool isInlineSpecified,
ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts)
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts,
+ SmallVector<Expr*> PostContracts)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
StartLoc),
DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
@@ -3093,6 +3108,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
if (TrailingRequiresClause)
setTrailingRequiresClause(TrailingRequiresClause);
setPreContracts(PreContracts);
+ setPostContracts(PostContracts);
}
void FunctionDecl::getNameForDiagnostic(
@@ -5416,10 +5432,11 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
bool isInlineSpecified, bool hasWrittenPrototype,
ConstexprSpecKind ConstexprKind,
- Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts,
+ SmallVector<Expr*> PostContracts) {
FunctionDecl *New = new (C, DC) FunctionDecl(
Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
- isInlineSpecified, ConstexprKind, TrailingRequiresClause, PreContracts);
+ isInlineSpecified, ConstexprKind, TrailingRequiresClause, PreContracts, PostContracts);
New->setHasWrittenPrototype(hasWrittenPrototype);
return New;
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index c7cf36bed83c6..b5a70feb0b7f8 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2276,10 +2276,11 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
bool isInline, ConstexprSpecKind ConstexprKind,
SourceLocation EndLocation,
- Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts,
+ SmallVector<Expr*> PostContracts) {
return new (C, RD) CXXMethodDecl(
CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
- isInline, ConstexprKind, EndLocation, TrailingRequiresClause, PreContracts);
+ isInline, ConstexprKind, EndLocation, TrailingRequiresClause, PreContracts, PostContracts);
}
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C,
@@ -2287,7 +2288,7 @@ CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C,
return new (C, ID) CXXMethodDecl(
CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
QualType(), nullptr, SC_None, false, false,
- ConstexprSpecKind::Unspecified, SourceLocation(), nullptr, {});
+ ConstexprSpecKind::Unspecified, SourceLocation(), nullptr, {}, {});
}
CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
@@ -2685,10 +2686,11 @@ CXXConstructorDecl::CXXConstructorDecl(
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
- InheritedConstructor Inherited, Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts)
+ InheritedConstructor Inherited, Expr *TrailingRequiresClause,
+ SmallVector<Expr*> PreContracts, SmallVector<Expr*> PostContracts)
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, UsesFPIntrin, isInline, ConstexprKind,
- SourceLocation(), TrailingRequiresClause, PreContracts) {
+ SourceLocation(), TrailingRequiresClause, PreContracts, PostContracts) {
setNumCtorInitializers(0);
setInheritingConstructor(static_cast<bool>(Inherited));
setImplicit(isImplicitlyDeclared);
@@ -2712,7 +2714,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
ExplicitSpecifier(), false, false, false, ConstexprSpecKind::Unspecified,
- InheritedConstructor(), nullptr, {});
+ InheritedConstructor(), nullptr, {}, {});
Result->setInheritingConstructor(isInheritingConstructor);
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
hasTrailingExplicit;
@@ -2725,7 +2727,8 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
- InheritedConstructor Inherited, Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
+ InheritedConstructor Inherited, Expr *TrailingRequiresClause,
+ SmallVector<Expr*> PreContracts, SmallVector<Expr*> PostContracts) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
@@ -2734,7 +2737,7 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
Inherited ? 1 : 0, ES.getExpr() ? 1 : 0);
return new (C, RD, Extra) CXXConstructorDecl(
C, RD, StartLoc, NameInfo, T, TInfo, ES, UsesFPIntrin, isInline,
- isImplicitlyDeclared, ConstexprKind, Inherited, TrailingRequiresClause, PreContracts);
+ isImplicitlyDeclared, ConstexprKind, Inherited, TrailingRequiresClause, PreContracts, PostContracts);
}
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
@@ -2858,13 +2861,14 @@ CXXDestructorDecl *CXXDestructorDecl::Create(
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
- ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
+ ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause,
+ SmallVector<Expr*> PreContracts, SmallVector<Expr*> PostContracts) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXDestructorName &&
"Name must refer to a destructor");
return new (C, RD) CXXDestructorDecl(
C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline,
- isImplicitlyDeclared, ConstexprKind, TrailingRequiresClause, PreContracts);
+ isImplicitlyDeclared, ConstexprKind, TrailingRequiresClause, PreContracts, PostContracts);
}
void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
@@ -2892,13 +2896,14 @@ CXXConversionDecl *CXXConversionDecl::Create(
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
- Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts) {
+ Expr *TrailingRequiresClause, SmallVector<Expr*> PreContracts,
+ SmallVector<Expr*> PostContracts) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConversionFunctionName &&
"Name must refer to a conversion function");
return new (C, RD) CXXConversionDecl(
C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline, ES,
- ConstexprKind, EndLocation, TrailingRequiresClause, PreContracts);
+ ConstexprKind, EndLocation, TrailingRequiresClause, PreContracts, PostContracts);
}
bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b8ec7eab44efd..8b56b0b0d8073 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6301,7 +6301,20 @@ static bool EvaluatePreContracts(const FunctionDecl* Callee, EvalInfo& Info) {
return false;
}
if (!Desired) {
- Info.CCEDiag(E, diag::note_constexpr_contract_failure);
+ Info.report(E->getSourceRange().getBegin(), diag::note_constexpr_contract_failure) << E->getSourceRange();
+ }
+ }
+ return true;
+}
+
+static bool EvaluatePostContracts(const FunctionDecl* Callee, EvalInfo& Info) {
+ for (Expr* E : Callee->getPostContracts()) {
+ APSInt Desired;
+ if (!EvaluateInteger(E, Desired, Info)){
+ return false;
+ }
+ if (!Desired) {
+ Info.report(E->getSourceRange().getBegin(), diag::note_constexpr_contract_failure) << E->getSourceRange();
}
}
return true;
@@ -6355,6 +6368,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
EvaluatePreContracts(Callee, Info);
StmtResult Ret = {Result, ResultSlot};
EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body);
+ EvaluatePostContracts(Callee, Info);
if (ESR == ESR_Succeeded) {
if (Callee->getReturnType()->isVoidType())
return true;
@@ -15529,7 +15543,7 @@ class VoidExprEvaluator
return false;
}
if (!Desired) {
- Info.CCEDiag(E->getArg(0), diag::note_constexpr_contract_failure);
+ Info.report(E->getArg(0)->getSourceRange().getBegin(), diag::note_constexpr_contract_failure) << E->getArg(0)->getSourceRange();
}
return true;
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 22665ec4b34f7..8864ecc211fcd 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -465,12 +465,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// Emit debug descriptor for function end.
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitFunctionEnd(Builder, CurFn);
-/*
- for (Expr* expr : FN->getPostContracts()) {
- EmitCXXContractCheck(expr);
- EmitCXXContractImply(expr);
- }
- */
// Reset the debug location to that of the simple 'return' expression, if any
// rather than that of the end of the function's scope '}'.
@@ -1251,11 +1245,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
- for (Expr* expr : FD->getPreContracts()) {
- EmitCXXContractCheck(expr);
- EmitCXXContractImply(expr);
- }
-
if (const CXXMethodDecl *MD = dyn_cast_if_present<CXXMethodDecl>(D);
MD && !MD->isStatic()) {
bool IsInLambda =
@@ -1535,6 +1524,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// Emit the standard function prologue.
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
+ for (Expr* expr : FD->getPreContracts()) {
+ EmitCXXContractCheck(expr);
+ EmitCXXContractImply(expr);
+ }
+
// Save parameters for coroutine function.
if (Body && isa_and_nonnull<CoroutineBodyStmt>(Body))
llvm::append_range(FnArgs, FD->parameters());
@@ -1610,6 +1604,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
}
}
+ for (Expr* expr : FD->getPostContracts()) {
+ EmitCXXContractCheck(expr);
+ EmitCXXContractImply(expr);
+ }
+
// Emit the standard function epilogue.
FinishFunction(BodyRange.getEnd());
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1853ac81ca829..c83b86f9d8816 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9325,7 +9325,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
SemaRef.getCurFPFeatures().isFPConstrained(), isInline, HasPrototype,
ConstexprSpecKind::Unspecified,
- /*TrailingRequiresClause=*/nullptr, {});
+ /*TrailingRequiresClause=*/nullptr, {}, {});
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -9335,6 +9335,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
Expr *TrailingRequiresClause = D.getTrailingRequiresClause();
SmallVector<Expr*> PreContracts = D.getPreContracts();
+ SmallVector<Expr*> PostContracts = D.getPostContracts();
SemaRef.CheckExplicitObjectMemberFunction(DC, D, Name, R);
@@ -9348,7 +9349,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
TInfo, ExplicitSpecifier, SemaRef.getCurFPFeatures().isFPConstrained(),
isInline, /*isImplicitlyDeclared=*/false, ConstexprKind,
- InheritedConstructor(), TrailingRequiresClause, PreContracts);
+ InheritedConstructor(), TrailingRequiresClause, PreContracts, PostContracts);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
@@ -9383,7 +9384,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return FunctionDecl::Create(
SemaRef.Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), Name, R,
TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
- /*hasPrototype=*/true, ConstexprKind, TrailingRequiresClause, PreContracts);
+ /*hasPrototype=*/true, ConstexprKind, TrailingRequiresClause, PreContracts, PostContracts);
}
} else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
@@ -9402,7 +9403,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
TInfo, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
ExplicitSpecifier, ConstexprKind, SourceLocation(),
- TrailingRequiresClause, PreContracts);
+ TrailingRequiresClause, PreContracts, PostContracts);
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
if (TrailingRequiresClause)
@@ -9431,7 +9432,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
CXXMethodDecl *Ret = CXXMethodDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
- ConstexprKind, SourceLocation(), TrailingRequiresClause, PreContracts);
+ ConstexprKind, SourceLocation(), TrailingRequiresClause, PreContracts, PostContracts);
IsVirtualOkay = !Ret->isStatic();
return Ret;
} else {
@@ -9446,7 +9447,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return FunctionDecl::Create(
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
SemaRef.getCurFPFeatures().isFPConstrained(), isInline,
- true /*HasPrototype*/, ConstexprKind, TrailingRequiresClause, PreContracts);
+ true /*HasPrototype*/, ConstexprKind, TrailingRequiresClause, PreContracts, PostContracts);
}
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 435223cc50b92..612e339a9aac7 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2164,6 +2164,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
SmallVector<Expr*> PreContracts = D->getPreContracts();
+ SmallVector<Expr*> PostContracts = D->getPostContracts();
// If we're instantiating a local function declaration, put the result
// in the enclosing namespace; otherwise we need to find the instantiated
@@ -2201,7 +2202,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
D->getCanonicalDecl()->getStorageClass(), D->UsesFPIntrin(),
D->isInlineSpecified(), D->hasWrittenPrototype(), D->getConstexprKind(),
- TrailingRequiresClause, PreContracts);
+ TrailingRequiresClause, PreContracts, PostContracts);
Function->setFriendConstraintRefersToEnclosingTemplate(
D->FriendConstraintRefersToEnclosingTemplate());
Function->setRangeEnd(D->getSourceRange().getEnd());
>From 027b095fb6ab958a29399871095aa2e1e844863a Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Mon, 3 Jun 2024 20:30:12 +0200
Subject: [PATCH 10/11] switch back to CCEDiag
---
clang/lib/AST/ExprConstant.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8b56b0b0d8073..eb62f558bfc46 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6301,7 +6301,7 @@ static bool EvaluatePreContracts(const FunctionDecl* Callee, EvalInfo& Info) {
return false;
}
if (!Desired) {
- Info.report(E->getSourceRange().getBegin(), diag::note_constexpr_contract_failure) << E->getSourceRange();
+ Info.CCEDiag(E, diag::note_constexpr_contract_failure);
}
}
return true;
@@ -6314,7 +6314,7 @@ static bool EvaluatePostContracts(const FunctionDecl* Callee, EvalInfo& Info) {
return false;
}
if (!Desired) {
- Info.report(E->getSourceRange().getBegin(), diag::note_constexpr_contract_failure) << E->getSourceRange();
+ Info.CCEDiag(E, diag::note_constexpr_contract_failure);
}
}
return true;
@@ -15543,7 +15543,7 @@ class VoidExprEvaluator
return false;
}
if (!Desired) {
- Info.report(E->getArg(0)->getSourceRange().getBegin(), diag::note_constexpr_contract_failure) << E->getArg(0)->getSourceRange();
+ Info.CCEDiag(E->getArg(0), diag::note_constexpr_contract_failure);
}
return true;
}
>From 075da514a4dd2d89bc30cef614547cbe961d0aea Mon Sep 17 00:00:00 2001
From: Dascandy <dascandy at gmail.com>
Date: Tue, 4 Jun 2024 10:24:07 +0200
Subject: [PATCH 11/11] use abort instead of terminate
---
libcxx/src/system_error.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/src/system_error.cpp b/libcxx/src/system_error.cpp
index de64edf199278..db145327cc2e7 100644
--- a/libcxx/src/system_error.cpp
+++ b/libcxx/src/system_error.cpp
@@ -221,7 +221,7 @@ void __throw_system_error(int ev, const char* what_arg) {
}
void contract_violation() {
- std::terminate();
+ std::abort();
}
_LIBCPP_END_NAMESPACE_STD
More information about the libcxx-commits
mailing list