forked from OSchip/llvm-project
[C++20] add Basic consteval specifier
Summary: this revision adds Lexing, Parsing and Basic Semantic for the consteval specifier as specified by http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1073r3.html with this patch, the consteval specifier is treated as constexpr but can only be applied to function declaration. Changes: - add the consteval keyword. - add parsing of consteval specifier for normal declarations and lambdas expressions. - add the whether a declaration is constexpr is now represented by and enum everywhere except for variable because they can't be consteval. - adapt diagnostic about constexpr to print constexpr or consteval depending on the case. - add tests for basic semantic. Reviewers: rsmith, martong, shafik Reviewed By: rsmith Subscribers: eraman, efriedma, rnkovacs, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D61790 llvm-svn: 363362
This commit is contained in:
parent
b63e577444
commit
796ed03b84
|
@ -1861,7 +1861,7 @@ protected:
|
|||
FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified,
|
||||
bool isConstexprSpecified);
|
||||
ConstexprSpecKind ConstexprKind);
|
||||
|
||||
using redeclarable_base = Redeclarable<FunctionDecl>;
|
||||
|
||||
|
@ -1891,29 +1891,24 @@ public:
|
|||
using redeclarable_base::getMostRecentDecl;
|
||||
using redeclarable_base::isFirstDecl;
|
||||
|
||||
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation NLoc,
|
||||
DeclarationName N, QualType T,
|
||||
TypeSourceInfo *TInfo,
|
||||
StorageClass SC,
|
||||
bool isInlineSpecified = false,
|
||||
bool hasWrittenPrototype = true,
|
||||
bool isConstexprSpecified = false) {
|
||||
static FunctionDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation NLoc, DeclarationName N, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified = false,
|
||||
bool hasWrittenPrototype = true,
|
||||
ConstexprSpecKind ConstexprKind = CSK_unspecified) {
|
||||
DeclarationNameInfo NameInfo(N, NLoc);
|
||||
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo,
|
||||
SC,
|
||||
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC,
|
||||
isInlineSpecified, hasWrittenPrototype,
|
||||
isConstexprSpecified);
|
||||
ConstexprKind);
|
||||
}
|
||||
|
||||
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC,
|
||||
bool isInlineSpecified,
|
||||
bool hasWrittenPrototype,
|
||||
bool isConstexprSpecified = false);
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass SC,
|
||||
bool isInlineSpecified, bool hasWrittenPrototype,
|
||||
ConstexprSpecKind ConstexprKind);
|
||||
|
||||
static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
|
@ -2110,8 +2105,21 @@ public:
|
|||
}
|
||||
|
||||
/// Whether this is a (C++11) constexpr function or constexpr constructor.
|
||||
bool isConstexpr() const { return FunctionDeclBits.IsConstexpr; }
|
||||
void setConstexpr(bool IC) { FunctionDeclBits.IsConstexpr = IC; }
|
||||
bool isConstexpr() const {
|
||||
return FunctionDeclBits.ConstexprKind != CSK_unspecified;
|
||||
}
|
||||
void setConstexprKind(ConstexprSpecKind CSK) {
|
||||
FunctionDeclBits.ConstexprKind = CSK;
|
||||
}
|
||||
ConstexprSpecKind getConstexprKind() const {
|
||||
return static_cast<ConstexprSpecKind>(FunctionDeclBits.ConstexprKind);
|
||||
}
|
||||
bool isConstexprSpecified() const {
|
||||
return FunctionDeclBits.ConstexprKind == CSK_constexpr;
|
||||
}
|
||||
bool isConsteval() const {
|
||||
return FunctionDeclBits.ConstexprKind == CSK_consteval;
|
||||
}
|
||||
|
||||
/// Whether the instantiation of this function is pending.
|
||||
/// This bit is set when the decision to instantiate this function is made
|
||||
|
|
|
@ -1500,7 +1500,9 @@ class DeclContext {
|
|||
uint64_t IsExplicitlyDefaulted : 1;
|
||||
uint64_t HasImplicitReturnZero : 1;
|
||||
uint64_t IsLateTemplateParsed : 1;
|
||||
uint64_t IsConstexpr : 1;
|
||||
|
||||
/// Kind of contexpr specifier as defined by ConstexprSpecKind.
|
||||
uint64_t ConstexprKind : 2;
|
||||
uint64_t InstantiationIsPending : 1;
|
||||
|
||||
/// Indicates if the function uses __try.
|
||||
|
@ -1528,7 +1530,7 @@ class DeclContext {
|
|||
};
|
||||
|
||||
/// Number of non-inherited bits in FunctionDeclBitfields.
|
||||
enum { NumFunctionDeclBits = 24 };
|
||||
enum { NumFunctionDeclBits = 25 };
|
||||
|
||||
/// Stores the bits used by CXXConstructorDecl. If modified
|
||||
/// NumCXXConstructorDeclBits and the accessor
|
||||
|
@ -1545,7 +1547,7 @@ class DeclContext {
|
|||
/// exactly 64 bits and thus the width of NumCtorInitializers
|
||||
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
|
||||
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
|
||||
uint64_t NumCtorInitializers : 24;
|
||||
uint64_t NumCtorInitializers : 23;
|
||||
uint64_t IsInheritingConstructor : 1;
|
||||
|
||||
/// Whether this constructor has a trail-allocated explicit specifier.
|
||||
|
|
|
@ -2057,7 +2057,7 @@ private:
|
|||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation)
|
||||
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, false, false),
|
||||
SC_None, false, CSK_unspecified),
|
||||
ExplicitSpec(ES) {
|
||||
if (EndLocation.isValid())
|
||||
setRangeEnd(EndLocation);
|
||||
|
@ -2112,11 +2112,11 @@ class CXXMethodDecl : public FunctionDecl {
|
|||
protected:
|
||||
CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation StartLoc, const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC, bool isInline,
|
||||
bool isConstexpr, SourceLocation EndLocation)
|
||||
: FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC, isInline, isConstexpr) {
|
||||
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
|
||||
bool isInline, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation)
|
||||
: FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline,
|
||||
ConstexprKind) {
|
||||
if (EndLocation.isValid())
|
||||
setRangeEnd(EndLocation);
|
||||
}
|
||||
|
@ -2124,11 +2124,9 @@ protected:
|
|||
public:
|
||||
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC,
|
||||
bool isInline,
|
||||
bool isConstexpr,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass SC,
|
||||
bool isInline, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation);
|
||||
|
||||
static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
@ -2575,7 +2573,7 @@ class CXXConstructorDecl final
|
|||
CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline,
|
||||
bool isImplicitlyDeclared, bool isConstexpr,
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
|
||||
InheritedConstructor Inherited);
|
||||
|
||||
void anchor() override;
|
||||
|
@ -2628,7 +2626,7 @@ public:
|
|||
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
|
||||
bool isConstexpr,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
InheritedConstructor Inherited = InheritedConstructor());
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifier() {
|
||||
|
@ -2834,12 +2832,11 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
|||
Expr *OperatorDeleteThisArg = nullptr;
|
||||
|
||||
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, /*isConstexpr=*/false, SourceLocation())
|
||||
{
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, bool isInline,
|
||||
bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, CSK_unspecified, SourceLocation()) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
|
@ -2890,9 +2887,9 @@ class CXXConversionDecl : public CXXMethodDecl {
|
|||
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES,
|
||||
bool isConstexpr, SourceLocation EndLocation)
|
||||
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation)
|
||||
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, isConstexpr, EndLocation),
|
||||
SC_None, isInline, ConstexprKind, EndLocation),
|
||||
ExplicitSpec(ES) {}
|
||||
void anchor() override;
|
||||
|
||||
|
@ -2907,7 +2904,7 @@ public:
|
|||
static CXXConversionDecl *
|
||||
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, ExplicitSpecifier ES, bool isConstexpr,
|
||||
bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation);
|
||||
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
|
|
|
@ -172,6 +172,9 @@ def ext_cxx11_longlong : Extension<
|
|||
def warn_cxx98_compat_longlong : Warning<
|
||||
"'long long' is incompatible with C++98">,
|
||||
InGroup<CXX98CompatPedantic>, DefaultIgnore;
|
||||
def warn_cxx20_compat_consteval : Warning<
|
||||
"consteval is incompatible with C++ standards before C++20">,
|
||||
InGroup<CXX2aCompat>, DefaultIgnore;
|
||||
def err_integer_literal_too_large : Error<
|
||||
"integer literal is too large to be represented in any %select{signed |}0"
|
||||
"integer type">;
|
||||
|
|
|
@ -360,7 +360,7 @@ def err_typename_invalid_storageclass : Error<
|
|||
def err_typename_invalid_functionspec : Error<
|
||||
"type name does not allow function specifier to be specified">;
|
||||
def err_typename_invalid_constexpr : Error<
|
||||
"type name does not allow constexpr specifier to be specified">;
|
||||
"type name does not allow %select{constexpr|consteval}0 specifier to be specified">;
|
||||
def err_typename_identifiers_only : Error<
|
||||
"typename is allowed for identifiers only">;
|
||||
|
||||
|
@ -875,9 +875,9 @@ def warn_cxx98_compat_lambda : Warning<
|
|||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def err_lambda_missing_parens : Error<
|
||||
"lambda requires '()' before %select{'mutable'|return type|"
|
||||
"attribute specifier|'constexpr'}0">;
|
||||
"attribute specifier|'constexpr'|'consteval'}0">;
|
||||
def err_lambda_decl_specifier_repeated : Error<
|
||||
"%select{'mutable'|'constexpr'}0 cannot appear multiple times in a lambda declarator">;
|
||||
"%select{'mutable'|'constexpr'|'consteval'}0 cannot appear multiple times in a lambda declarator">;
|
||||
def err_lambda_capture_misplaced_ellipsis : Error<
|
||||
"ellipsis in pack %select{|init-}0capture must appear %select{after|before}0 "
|
||||
"the name of the capture">;
|
||||
|
|
|
@ -704,7 +704,7 @@ def ext_noreturn_main : ExtWarn<
|
|||
"'main' is not allowed to be declared _Noreturn">, InGroup<Main>;
|
||||
def note_main_remove_noreturn : Note<"remove '_Noreturn'">;
|
||||
def err_constexpr_main : Error<
|
||||
"'main' is not allowed to be declared constexpr">;
|
||||
"'main' is not allowed to be declared %select{constexpr|consteval}0">;
|
||||
def err_deleted_main : Error<"'main' is not allowed to be deleted">;
|
||||
def err_mainlike_template_decl : Error<"%0 cannot be a template">;
|
||||
def err_main_returns_nonint : Error<"'main' must return 'int'">;
|
||||
|
@ -2312,14 +2312,17 @@ def warn_cxx14_compat_constexpr_not_const : Warning<
|
|||
InGroup<DiagGroup<"constexpr-not-const">>;
|
||||
def err_invalid_constexpr : Error<
|
||||
"%select{function parameter|typedef|non-static data member}0 "
|
||||
"cannot be constexpr">;
|
||||
"cannot be %select{constexpr|consteval}1">;
|
||||
def err_invalid_constexpr_member : Error<"non-static data member cannot be "
|
||||
"constexpr%select{; did you intend to make it %select{const|static}0?|}1">;
|
||||
def err_constexpr_tag : Error<
|
||||
"%select{class|struct|interface|union|enum}0 cannot be marked constexpr">;
|
||||
def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
|
||||
def err_constexpr_no_declarators : Error<
|
||||
"constexpr can only be used in variable and function declarations">;
|
||||
"%select{class|struct|interface|union|enum}0 "
|
||||
"cannot be marked %select{constexpr|consteval}1">;
|
||||
def err_constexpr_dtor : Error<
|
||||
"destructor cannot be marked %select{constexpr|consteval}0">;
|
||||
def err_constexpr_wrong_decl_kind : Error<
|
||||
"%select{constexpr|consteval}0 can only be used "
|
||||
"in %select{variable and |}0function declarations">;
|
||||
def err_invalid_constexpr_var_decl : Error<
|
||||
"constexpr variable declaration must be a definition">;
|
||||
def err_constexpr_static_mem_var_requires_init : Error<
|
||||
|
@ -2329,8 +2332,8 @@ def err_constexpr_var_non_literal : Error<
|
|||
def err_constexpr_var_requires_const_init : Error<
|
||||
"constexpr variable %0 must be initialized by a constant expression">;
|
||||
def err_constexpr_redecl_mismatch : Error<
|
||||
"%select{non-constexpr declaration of %0 follows constexpr declaration"
|
||||
"|constexpr declaration of %0 follows non-constexpr declaration}1">;
|
||||
"%select{non-constexpr|constexpr|consteval}1 declaration of %0"
|
||||
" follows %select{non-constexpr|constexpr|consteval}2 declaration">;
|
||||
def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
|
||||
def warn_cxx17_compat_constexpr_virtual : Warning<
|
||||
"virtual constexpr functions are incompatible with "
|
||||
|
@ -2345,12 +2348,12 @@ def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
|
|||
"with virtual base %plural{1:class|:classes}1 is not a literal type">;
|
||||
def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
|
||||
def err_constexpr_non_literal_return : Error<
|
||||
"constexpr function's return type %0 is not a literal type">;
|
||||
"%select{constexpr|consteval}0 function's return type %1 is not a literal type">;
|
||||
def err_constexpr_non_literal_param : Error<
|
||||
"constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is "
|
||||
"%select{constexpr|consteval}2 %select{function|constructor}1's %ordinal0 parameter type %3 is "
|
||||
"not a literal type">;
|
||||
def err_constexpr_body_invalid_stmt : Error<
|
||||
"statement not allowed in constexpr %select{function|constructor}0">;
|
||||
"statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">;
|
||||
def ext_constexpr_body_invalid_stmt : ExtWarn<
|
||||
"use of this statement in a constexpr %select{function|constructor}0 "
|
||||
"is a C++14 extension">, InGroup<CXX14>;
|
||||
|
@ -2400,9 +2403,9 @@ def err_diagnose_if_invalid_diagnostic_type : Error<
|
|||
"invalid diagnostic type for 'diagnose_if'; use \"error\" or \"warning\" "
|
||||
"instead">;
|
||||
def err_constexpr_body_no_return : Error<
|
||||
"no return statement in constexpr function">;
|
||||
"no return statement in %select{constexpr|consteval}0 function">;
|
||||
def err_constexpr_return_missing_expr : Error<
|
||||
"non-void constexpr function %0 should return a value">;
|
||||
"non-void %select{constexpr|consteval}1 function %0 should return a value">;
|
||||
def warn_cxx11_compat_constexpr_body_no_return : Warning<
|
||||
"constexpr function with no return statements is incompatible with C++ "
|
||||
"standards before C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
|
||||
|
@ -7853,6 +7856,9 @@ def err_defaulted_copy_assign_not_ref : Error<
|
|||
def err_incorrect_defaulted_constexpr : Error<
|
||||
"defaulted definition of %sub{select_special_member_kind}0 "
|
||||
"is not constexpr">;
|
||||
def err_incorrect_defaulted_consteval : Error<
|
||||
"defaulted declaration of %sub{select_special_member_kind}0 "
|
||||
"cannot be consteval because implicit definition is not constexpr">;
|
||||
def warn_defaulted_method_deleted : Warning<
|
||||
"explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
|
||||
"deleted">, InGroup<DiagGroup<"defaulted-function-deleted">>;
|
||||
|
@ -9422,7 +9428,7 @@ def err_coroutine_invalid_func_context : Error<
|
|||
"'%1' cannot be used in %select{a constructor|a destructor"
|
||||
"|a copy assignment operator|a move assignment operator|the 'main' function"
|
||||
"|a constexpr function|a function with a deduced return type"
|
||||
"|a varargs function}0">;
|
||||
"|a varargs function|a consteval function}0">;
|
||||
def err_implied_coroutine_type_not_found : Error<
|
||||
"%0 type was not found; include <experimental/coroutine> before defining "
|
||||
"a coroutine">;
|
||||
|
@ -9660,7 +9666,7 @@ def err_multiversion_doesnt_support : Error<
|
|||
"attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not "
|
||||
"yet support %select{function templates|virtual functions|"
|
||||
"deduced return types|constructors|destructors|deleted functions|"
|
||||
"defaulted functions|constexpr functions}1">;
|
||||
"defaulted functions|constexpr functions|consteval function}1">;
|
||||
def err_multiversion_not_allowed_on_main : Error<
|
||||
"'main' cannot be a multiversioned function">;
|
||||
def err_multiversion_not_supported : Error<
|
||||
|
|
|
@ -28,6 +28,13 @@ namespace clang {
|
|||
Unresolved,
|
||||
};
|
||||
|
||||
/// Define the kind of constexpr specifier.
|
||||
enum ConstexprSpecKind {
|
||||
CSK_unspecified,
|
||||
CSK_constexpr,
|
||||
CSK_consteval
|
||||
};
|
||||
|
||||
/// Specifies the width of a type, e.g., short, long, or long long.
|
||||
enum TypeSpecifierWidth {
|
||||
TSW_unspecified,
|
||||
|
|
|
@ -384,8 +384,9 @@ COROUTINES_KEYWORD(co_yield)
|
|||
MODULES_KEYWORD(module)
|
||||
MODULES_KEYWORD(import)
|
||||
|
||||
// C++ char8_t proposal
|
||||
// C++20 keywords.
|
||||
CXX2A_KEYWORD(char8_t , CHAR8SUPPORT)
|
||||
CXX2A_KEYWORD(consteval , 0)
|
||||
|
||||
// C11 Extension
|
||||
KEYWORD(_Float16 , KEYALL)
|
||||
|
|
|
@ -363,7 +363,7 @@ private:
|
|||
unsigned Friend_specified : 1;
|
||||
|
||||
// constexpr-specifier
|
||||
unsigned Constexpr_specified : 1;
|
||||
ConstexprSpecKind ConstexprSpecifier : 2;
|
||||
|
||||
union {
|
||||
UnionParsedType TypeRep;
|
||||
|
@ -433,7 +433,7 @@ public:
|
|||
TypeSpecPipe(false), TypeSpecSat(false), TypeQualifiers(TQ_unspecified),
|
||||
FS_inline_specified(false), FS_forceinline_specified(false),
|
||||
FS_virtual_specified(false), FS_noreturn_specified(false),
|
||||
Friend_specified(false), Constexpr_specified(false),
|
||||
Friend_specified(false), ConstexprSpecifier(CSK_unspecified),
|
||||
FS_explicit_specifier(), Attrs(attrFactory), writtenBS(),
|
||||
ObjCQualifiers(nullptr) {}
|
||||
|
||||
|
@ -530,6 +530,7 @@ public:
|
|||
static const char *getSpecifierName(DeclSpec::TSW W);
|
||||
static const char *getSpecifierName(DeclSpec::SCS S);
|
||||
static const char *getSpecifierName(DeclSpec::TSCS S);
|
||||
static const char *getSpecifierName(ConstexprSpecKind C);
|
||||
|
||||
// type-qualifiers
|
||||
|
||||
|
@ -718,8 +719,8 @@ public:
|
|||
unsigned &DiagID);
|
||||
bool setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
bool SetConstexprSpec(ConstexprSpecKind ConstexprKind, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID);
|
||||
|
||||
bool isFriendSpecified() const { return Friend_specified; }
|
||||
SourceLocation getFriendSpecLoc() const { return FriendLoc; }
|
||||
|
@ -727,11 +728,14 @@ public:
|
|||
bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
|
||||
SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; }
|
||||
|
||||
bool isConstexprSpecified() const { return Constexpr_specified; }
|
||||
ConstexprSpecKind getConstexprSpecifier() const { return ConstexprSpecifier; }
|
||||
SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
|
||||
bool hasConstexprSpecifier() const {
|
||||
return ConstexprSpecifier != CSK_unspecified;
|
||||
}
|
||||
|
||||
void ClearConstexprSpec() {
|
||||
Constexpr_specified = false;
|
||||
ConstexprSpecifier = CSK_unspecified;
|
||||
ConstexprLoc = SourceLocation();
|
||||
}
|
||||
|
||||
|
|
|
@ -5746,7 +5746,7 @@ public:
|
|||
startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange,
|
||||
TypeSourceInfo *MethodType, SourceLocation EndLoc,
|
||||
ArrayRef<ParmVarDecl *> Params,
|
||||
bool IsConstexprSpecified,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Optional<std::pair<unsigned, Decl *>> Mangling = None);
|
||||
|
||||
/// Endow the lambda scope info with the relevant properties.
|
||||
|
|
|
@ -3093,7 +3093,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
ExplicitSpecifier(
|
||||
ExplicitExpr,
|
||||
FromConstructor->getExplicitSpecifier().getKind()),
|
||||
D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
|
||||
D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind()))
|
||||
return ToFunction;
|
||||
} else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {
|
||||
|
||||
|
@ -3131,19 +3131,20 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
|
||||
ExplicitSpecifier(ExplicitExpr,
|
||||
FromConversion->getExplicitSpecifier().getKind()),
|
||||
D->isConstexpr(), SourceLocation()))
|
||||
D->getConstexprKind(), SourceLocation()))
|
||||
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->isInlineSpecified(), D->isConstexpr(), SourceLocation()))
|
||||
Method->isInlineSpecified(), D->getConstexprKind(),
|
||||
SourceLocation()))
|
||||
return ToFunction;
|
||||
} else {
|
||||
if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC,
|
||||
ToInnerLocStart, NameInfo, T, TInfo,
|
||||
D->getStorageClass(), D->isInlineSpecified(),
|
||||
D->hasWrittenPrototype(), D->isConstexpr()))
|
||||
if (GetImportedOrCreateDecl(
|
||||
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
|
||||
NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(),
|
||||
D->hasWrittenPrototype(), D->getConstexprKind()))
|
||||
return ToFunction;
|
||||
}
|
||||
|
||||
|
|
|
@ -2724,7 +2724,8 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
|||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S,
|
||||
bool isInlineSpecified, bool isConstexprSpecified)
|
||||
bool isInlineSpecified,
|
||||
ConstexprSpecKind ConstexprKind)
|
||||
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
|
||||
StartLoc),
|
||||
DeclContext(DK), redeclarable_base(C), ODRHash(0),
|
||||
|
@ -2744,7 +2745,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
|||
FunctionDeclBits.IsExplicitlyDefaulted = false;
|
||||
FunctionDeclBits.HasImplicitReturnZero = false;
|
||||
FunctionDeclBits.IsLateTemplateParsed = false;
|
||||
FunctionDeclBits.IsConstexpr = isConstexprSpecified;
|
||||
FunctionDeclBits.ConstexprKind = ConstexprKind;
|
||||
FunctionDeclBits.InstantiationIsPending = false;
|
||||
FunctionDeclBits.UsesSEHTry = false;
|
||||
FunctionDeclBits.HasSkippedBody = false;
|
||||
|
@ -4541,13 +4542,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC,
|
||||
bool isInlineSpecified,
|
||||
StorageClass SC, bool isInlineSpecified,
|
||||
bool hasWrittenPrototype,
|
||||
bool isConstexprSpecified) {
|
||||
ConstexprSpecKind ConstexprKind) {
|
||||
FunctionDecl *New =
|
||||
new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo,
|
||||
SC, isInlineSpecified, isConstexprSpecified);
|
||||
SC, isInlineSpecified, ConstexprKind);
|
||||
New->setHasWrittenPrototype(hasWrittenPrototype);
|
||||
return New;
|
||||
}
|
||||
|
@ -4555,7 +4555,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||
return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(),
|
||||
DeclarationNameInfo(), QualType(), nullptr,
|
||||
SC_None, false, false);
|
||||
SC_None, false, CSK_unspecified);
|
||||
}
|
||||
|
||||
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
||||
|
|
|
@ -1995,22 +1995,22 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CXXMethodDecl *
|
||||
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC, bool isInline,
|
||||
bool isConstexpr, SourceLocation EndLocation) {
|
||||
return new (C, RD) CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo,
|
||||
T, TInfo, SC, isInline, isConstexpr,
|
||||
EndLocation);
|
||||
CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC, bool isInline,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation) {
|
||||
return new (C, RD)
|
||||
CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC,
|
||||
isInline, ConstexprKind, EndLocation);
|
||||
}
|
||||
|
||||
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||
return new (C, ID) CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(),
|
||||
DeclarationNameInfo(), QualType(), nullptr,
|
||||
SC_None, false, false, SourceLocation());
|
||||
return new (C, ID) CXXMethodDecl(
|
||||
CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
|
||||
QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation());
|
||||
}
|
||||
|
||||
CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
|
||||
|
@ -2367,9 +2367,9 @@ CXXConstructorDecl::CXXConstructorDecl(
|
|||
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
|
||||
bool isConstexpr, InheritedConstructor Inherited)
|
||||
ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited)
|
||||
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, isConstexpr, SourceLocation()) {
|
||||
SC_None, isInline, ConstexprKind, SourceLocation()) {
|
||||
setNumCtorInitializers(0);
|
||||
setInheritingConstructor(static_cast<bool>(Inherited));
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
|
@ -2390,9 +2390,10 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
|
|||
unsigned Extra =
|
||||
additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
|
||||
isInheritingConstructor, hasTraillingExplicit);
|
||||
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
|
||||
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
|
||||
ExplicitSpecifier(), false, false, false, InheritedConstructor());
|
||||
auto *Result = new (C, ID, Extra)
|
||||
CXXConstructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(),
|
||||
QualType(), nullptr, ExplicitSpecifier(), false, false,
|
||||
CSK_unspecified, InheritedConstructor());
|
||||
Result->setInheritingConstructor(isInheritingConstructor);
|
||||
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
|
||||
hasTraillingExplicit;
|
||||
|
@ -2404,7 +2405,7 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
|
|||
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
|
||||
bool isConstexpr, InheritedConstructor Inherited) {
|
||||
ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited) {
|
||||
assert(NameInfo.getName().getNameKind()
|
||||
== DeclarationName::CXXConstructorName &&
|
||||
"Name must refer to a constructor");
|
||||
|
@ -2413,7 +2414,7 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
|
|||
Inherited ? 1 : 0, ES.getExpr() ? 1 : 0);
|
||||
return new (C, RD, Extra)
|
||||
CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline,
|
||||
isImplicitlyDeclared, isConstexpr, Inherited);
|
||||
isImplicitlyDeclared, ConstexprKind, Inherited);
|
||||
}
|
||||
|
||||
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
|
||||
|
@ -2566,19 +2567,20 @@ CXXConversionDecl *
|
|||
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||
return new (C, ID) CXXConversionDecl(
|
||||
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
|
||||
false, ExplicitSpecifier(), false, SourceLocation());
|
||||
false, ExplicitSpecifier(), CSK_unspecified, SourceLocation());
|
||||
}
|
||||
|
||||
CXXConversionDecl *CXXConversionDecl::Create(
|
||||
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, ExplicitSpecifier ES, bool isConstexpr,
|
||||
bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation) {
|
||||
assert(NameInfo.getName().getNameKind()
|
||||
== DeclarationName::CXXConversionFunctionName &&
|
||||
"Name must refer to a conversion function");
|
||||
return new (C, RD) CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
isInline, ES, isConstexpr, EndLocation);
|
||||
return new (C, RD)
|
||||
CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, ES,
|
||||
ConstexprKind, EndLocation);
|
||||
}
|
||||
|
||||
bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
|
||||
|
|
|
@ -610,7 +610,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
if (D->isInlineSpecified()) Out << "inline ";
|
||||
if (D->isVirtualAsWritten()) Out << "virtual ";
|
||||
if (D->isModulePrivate()) Out << "__module_private__ ";
|
||||
if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
|
||||
if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted())
|
||||
Out << "constexpr ";
|
||||
if (D->isConsteval()) Out << "consteval ";
|
||||
ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);
|
||||
if (ExplicitSpec.isSpecified())
|
||||
printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation);
|
||||
|
|
|
@ -255,9 +255,12 @@ void TextNodeDumper::Visit(const Decl *D) {
|
|||
|
||||
if (D->isInvalidDecl())
|
||||
OS << " invalid";
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
if (FD->isConstexpr())
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->isConstexprSpecified())
|
||||
OS << " constexpr";
|
||||
if (FD->isConsteval())
|
||||
OS << " consteval";
|
||||
}
|
||||
|
||||
if (!isa<FunctionDecl>(*D)) {
|
||||
const auto *MD = dyn_cast<ObjCMethodDecl>(D);
|
||||
|
|
|
@ -109,7 +109,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
|
|||
// the tokens and store them for parsing at the end of the translation unit.
|
||||
if (getLangOpts().DelayedTemplateParsing &&
|
||||
D.getFunctionDefinitionKind() == FDK_Definition &&
|
||||
!D.getDeclSpec().isConstexprSpecified() &&
|
||||
!D.getDeclSpec().hasConstexprSpecifier() &&
|
||||
!(FnD && FnD->getAsFunction() &&
|
||||
FnD->getAsFunction()->getReturnType()->getContainedAutoType()) &&
|
||||
((Actions.CurContext->isDependentContext() ||
|
||||
|
|
|
@ -2487,8 +2487,9 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
|
|||
}
|
||||
|
||||
// Issue diagnostic and remove constexpr specifier if present.
|
||||
if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) {
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
|
||||
if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) {
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr)
|
||||
<< (DS.getConstexprSpecifier() == CSK_consteval);
|
||||
DS.ClearConstexprSpec();
|
||||
}
|
||||
}
|
||||
|
@ -3626,7 +3627,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
|
||||
// constexpr
|
||||
case tok::kw_constexpr:
|
||||
isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
|
||||
isInvalid = DS.SetConstexprSpec(CSK_constexpr, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
|
||||
// consteval
|
||||
case tok::kw_consteval:
|
||||
isInvalid = DS.SetConstexprSpec(CSK_consteval, Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
|
||||
// type-specifier
|
||||
|
@ -5031,6 +5037,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
|
|||
case tok::annot_decltype:
|
||||
case tok::kw_constexpr:
|
||||
|
||||
// C++20 consteval.
|
||||
case tok::kw_consteval:
|
||||
|
||||
// C11 _Atomic
|
||||
case tok::kw__Atomic:
|
||||
return true;
|
||||
|
@ -6267,7 +6276,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
|||
Actions.CurContext->isRecord());
|
||||
|
||||
Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
|
||||
if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14)
|
||||
if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)
|
||||
Q.addConst();
|
||||
// FIXME: Collect C++ address spaces.
|
||||
// If there are multiple different address spaces, the source is invalid.
|
||||
|
|
|
@ -1101,10 +1101,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
tryConsumeMutableOrConstexprToken(Parser &P, SourceLocation &MutableLoc,
|
||||
SourceLocation &ConstexprLoc,
|
||||
SourceLocation &DeclEndLoc) {
|
||||
static void tryConsumeLambdaSpecifierToken(Parser &P,
|
||||
SourceLocation &MutableLoc,
|
||||
SourceLocation &ConstexprLoc,
|
||||
SourceLocation &ConstevalLoc,
|
||||
SourceLocation &DeclEndLoc) {
|
||||
assert(MutableLoc.isInvalid());
|
||||
assert(ConstexprLoc.isInvalid());
|
||||
// Consume constexpr-opt mutable-opt in any sequence, and set the DeclEndLoc
|
||||
|
@ -1132,6 +1133,15 @@ tryConsumeMutableOrConstexprToken(Parser &P, SourceLocation &MutableLoc,
|
|||
ConstexprLoc = P.ConsumeToken();
|
||||
DeclEndLoc = ConstexprLoc;
|
||||
break /*switch*/;
|
||||
case tok::kw_consteval:
|
||||
if (ConstevalLoc.isValid()) {
|
||||
P.Diag(P.getCurToken().getLocation(),
|
||||
diag::err_lambda_decl_specifier_repeated)
|
||||
<< 2 << FixItHint::CreateRemoval(P.getCurToken().getLocation());
|
||||
}
|
||||
ConstevalLoc = P.ConsumeToken();
|
||||
DeclEndLoc = ConstevalLoc;
|
||||
break /*switch*/;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -1147,12 +1157,25 @@ addConstexprToLambdaDeclSpecifier(Parser &P, SourceLocation ConstexprLoc,
|
|||
: diag::warn_cxx14_compat_constexpr_on_lambda);
|
||||
const char *PrevSpec = nullptr;
|
||||
unsigned DiagID = 0;
|
||||
DS.SetConstexprSpec(ConstexprLoc, PrevSpec, DiagID);
|
||||
DS.SetConstexprSpec(CSK_constexpr, ConstexprLoc, PrevSpec, DiagID);
|
||||
assert(PrevSpec == nullptr && DiagID == 0 &&
|
||||
"Constexpr cannot have been set previously!");
|
||||
}
|
||||
}
|
||||
|
||||
static void addConstevalToLambdaDeclSpecifier(Parser &P,
|
||||
SourceLocation ConstevalLoc,
|
||||
DeclSpec &DS) {
|
||||
if (ConstevalLoc.isValid()) {
|
||||
P.Diag(ConstevalLoc, diag::warn_cxx20_compat_consteval);
|
||||
const char *PrevSpec = nullptr;
|
||||
unsigned DiagID = 0;
|
||||
DS.SetConstexprSpec(CSK_consteval, ConstevalLoc, PrevSpec, DiagID);
|
||||
if (DiagID != 0)
|
||||
P.Diag(ConstevalLoc, DiagID) << PrevSpec;
|
||||
}
|
||||
}
|
||||
|
||||
/// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda
|
||||
/// expression.
|
||||
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
||||
|
@ -1263,14 +1286,16 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
// compatible with MSVC.
|
||||
MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc);
|
||||
|
||||
// Parse mutable-opt and/or constexpr-opt, and update the DeclEndLoc.
|
||||
// Parse mutable-opt and/or constexpr-opt or consteval-opt, and update the
|
||||
// DeclEndLoc.
|
||||
SourceLocation MutableLoc;
|
||||
SourceLocation ConstexprLoc;
|
||||
tryConsumeMutableOrConstexprToken(*this, MutableLoc, ConstexprLoc,
|
||||
DeclEndLoc);
|
||||
SourceLocation ConstevalLoc;
|
||||
tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
|
||||
ConstevalLoc, DeclEndLoc);
|
||||
|
||||
addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
|
||||
|
||||
addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
|
||||
// Parse exception-specification[opt].
|
||||
ExceptionSpecificationType ESpecType = EST_None;
|
||||
SourceRange ESpecRange;
|
||||
|
@ -1322,7 +1347,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
TrailingReturnType),
|
||||
std::move(Attr), DeclEndLoc);
|
||||
} else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
|
||||
tok::kw_constexpr) ||
|
||||
tok::kw_constexpr, tok::kw_consteval) ||
|
||||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
|
||||
// It's common to forget that one needs '()' before 'mutable', an attribute
|
||||
// specifier, or the result type. Deal with this.
|
||||
|
@ -1333,6 +1358,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
case tok::kw___attribute:
|
||||
case tok::l_square: TokKind = 2; break;
|
||||
case tok::kw_constexpr: TokKind = 3; break;
|
||||
case tok::kw_consteval: TokKind = 4; break;
|
||||
default: llvm_unreachable("Unknown token kind");
|
||||
}
|
||||
|
||||
|
|
|
@ -1221,6 +1221,7 @@ public:
|
|||
/// 'friend'
|
||||
/// 'typedef'
|
||||
/// [C++11] 'constexpr'
|
||||
/// [C++20] 'consteval'
|
||||
/// [GNU] attributes declaration-specifiers[opt]
|
||||
///
|
||||
/// storage-class-specifier:
|
||||
|
@ -1406,6 +1407,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
|
|||
case tok::kw_friend:
|
||||
case tok::kw_typedef:
|
||||
case tok::kw_constexpr:
|
||||
case tok::kw_consteval:
|
||||
// storage-class-specifier
|
||||
case tok::kw_register:
|
||||
case tok::kw_static:
|
||||
|
|
|
@ -564,6 +564,15 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
|
|||
llvm_unreachable("Unknown typespec!");
|
||||
}
|
||||
|
||||
const char *DeclSpec::getSpecifierName(ConstexprSpecKind C) {
|
||||
switch (C) {
|
||||
case CSK_unspecified: return "unspecified";
|
||||
case CSK_constexpr: return "constexpr";
|
||||
case CSK_consteval: return "consteval";
|
||||
}
|
||||
llvm_unreachable("Unknown ConstexprSpecKind");
|
||||
}
|
||||
|
||||
const char *DeclSpec::getSpecifierName(TQ T) {
|
||||
switch (T) {
|
||||
case DeclSpec::TQ_unspecified: return "unspecified";
|
||||
|
@ -1025,16 +1034,17 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
bool DeclSpec::SetConstexprSpec(ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID) {
|
||||
// 'constexpr constexpr' is ok, but warn as this is likely not what the user
|
||||
// intended.
|
||||
if (Constexpr_specified) {
|
||||
if (ConstexprSpecifier != CSK_unspecified) {
|
||||
if (ConstexprSpecifier == CSK_consteval || ConstexprKind == CSK_consteval)
|
||||
return BadSpecifier(ConstexprKind, ConstexprSpecifier, PrevSpec, DiagID);
|
||||
DiagID = diag::warn_duplicate_declspec;
|
||||
PrevSpec = "constexpr";
|
||||
return true;
|
||||
}
|
||||
Constexpr_specified = true;
|
||||
ConstexprSpecifier = ConstexprKind;
|
||||
ConstexprLoc = Loc;
|
||||
return false;
|
||||
}
|
||||
|
@ -1280,9 +1290,10 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
|||
else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
|
||||
S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
|
||||
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
|
||||
if (Constexpr_specified)
|
||||
if (getConstexprSpecifier() == CSK_constexpr)
|
||||
S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr);
|
||||
|
||||
if (getConstexprSpecifier() == CSK_consteval)
|
||||
S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval);
|
||||
// C++ [class.friend]p6:
|
||||
// No storage-class-specifier shall appear in the decl-specifier-seq
|
||||
// of a friend declaration.
|
||||
|
|
|
@ -210,6 +210,7 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
|
|||
DiagConstexpr,
|
||||
DiagAutoRet,
|
||||
DiagVarargs,
|
||||
DiagConsteval,
|
||||
};
|
||||
bool Diagnosed = false;
|
||||
auto DiagInvalid = [&](InvalidFuncDiag ID) {
|
||||
|
@ -244,7 +245,7 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
|
|||
// evaluation of e [...] would evaluate one of the following expressions:
|
||||
// [...] an await-expression [...] a yield-expression."
|
||||
if (FD->isConstexpr())
|
||||
DiagInvalid(DiagConstexpr);
|
||||
DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);
|
||||
// [dcl.spec.auto]p15: "A function declared with a return type that uses a
|
||||
// placeholder type shall not be a coroutine."
|
||||
if (FD->getReturnType()->isUndeducedType())
|
||||
|
|
|
@ -4292,14 +4292,18 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
|
|||
Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)
|
||||
<< getLangOpts().CPlusPlus17;
|
||||
|
||||
if (DS.isConstexprSpecified()) {
|
||||
if (DS.hasConstexprSpecifier()) {
|
||||
// C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations
|
||||
// and definitions of functions and variables.
|
||||
// C++2a [dcl.constexpr]p1: The consteval specifier shall be applied only to
|
||||
// the declaration of a function or function template
|
||||
bool IsConsteval = DS.getConstexprSpecifier() == CSK_consteval;
|
||||
if (Tag)
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
|
||||
<< GetDiagnosticTypeSpecifierID(DS.getTypeSpecType());
|
||||
<< GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << IsConsteval;
|
||||
else
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind)
|
||||
<< IsConsteval;
|
||||
// Don't emit warnings after this error.
|
||||
return TagD;
|
||||
}
|
||||
|
@ -5752,9 +5756,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
if (D.getDeclSpec().isInlineSpecified())
|
||||
Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
|
||||
<< getLangOpts().CPlusPlus17;
|
||||
if (D.getDeclSpec().isConstexprSpecified())
|
||||
if (D.getDeclSpec().hasConstexprSpecifier())
|
||||
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
|
||||
<< 1;
|
||||
<< 1 << (D.getDeclSpec().getConstexprSpecifier() == CSK_consteval);
|
||||
|
||||
if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) {
|
||||
if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName)
|
||||
|
@ -6648,13 +6652,17 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
|||
NewVD->setTemplateParameterListsInfo(
|
||||
Context, TemplateParamLists.drop_back(VDTemplateParamLists));
|
||||
|
||||
if (D.getDeclSpec().isConstexprSpecified()) {
|
||||
if (D.getDeclSpec().hasConstexprSpecifier()) {
|
||||
NewVD->setConstexpr(true);
|
||||
// C++1z [dcl.spec.constexpr]p1:
|
||||
// A static data member declared with the constexpr specifier is
|
||||
// implicitly an inline variable.
|
||||
if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus17)
|
||||
NewVD->setImplicitlyInline();
|
||||
if (D.getDeclSpec().getConstexprSpecifier() == CSK_consteval)
|
||||
Diag(D.getDeclSpec().getConstexprSpecLoc(),
|
||||
diag::err_constexpr_wrong_decl_kind)
|
||||
<< /*consteval*/ 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7982,7 +7990,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
(!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
|
||||
|
||||
NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
|
||||
R, TInfo, SC, isInline, HasPrototype, false);
|
||||
R, TInfo, SC, isInline, HasPrototype,
|
||||
CSK_unspecified);
|
||||
if (D.isInvalidType())
|
||||
NewFD->setInvalidDecl();
|
||||
|
||||
|
@ -7990,8 +7999,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
}
|
||||
|
||||
ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
|
||||
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
|
||||
|
||||
ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
|
||||
// Check that the return type is not an abstract class type.
|
||||
// For record types, this is done by the AbstractClassUsageDiagnoser once
|
||||
// the class has been completely parsed.
|
||||
|
@ -8010,7 +8018,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
return CXXConstructorDecl::Create(
|
||||
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
|
||||
TInfo, ExplicitSpecifier, isInline,
|
||||
/*isImplicitlyDeclared=*/false, isConstexpr);
|
||||
/*isImplicitlyDeclared=*/false, ConstexprKind);
|
||||
|
||||
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
|
||||
// This is a C++ destructor declaration.
|
||||
|
@ -8040,7 +8048,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
|
||||
D.getIdentifierLoc(), Name, R, TInfo, SC,
|
||||
isInline,
|
||||
/*hasPrototype=*/true, isConstexpr);
|
||||
/*hasPrototype=*/true, ConstexprKind);
|
||||
}
|
||||
|
||||
} else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
|
||||
|
@ -8054,7 +8062,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
IsVirtualOkay = true;
|
||||
return CXXConversionDecl::Create(
|
||||
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
|
||||
TInfo, isInline, ExplicitSpecifier, isConstexpr, SourceLocation());
|
||||
TInfo, isInline, ExplicitSpecifier, ConstexprKind, SourceLocation());
|
||||
|
||||
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
|
||||
SemaRef.CheckDeductionGuideDeclarator(D, R, SC);
|
||||
|
@ -8078,7 +8086,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
// This is a C++ method declaration.
|
||||
CXXMethodDecl *Ret = CXXMethodDecl::Create(
|
||||
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
|
||||
TInfo, SC, isInline, isConstexpr, SourceLocation());
|
||||
TInfo, SC, isInline, ConstexprKind, SourceLocation());
|
||||
IsVirtualOkay = !Ret->isStatic();
|
||||
return Ret;
|
||||
} else {
|
||||
|
@ -8092,7 +8100,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
// - we're in C++ (where every function has a prototype),
|
||||
return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
|
||||
R, TInfo, SC, isInline, true /*HasPrototype*/,
|
||||
isConstexpr);
|
||||
ConstexprKind);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8422,7 +8430,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
bool isInline = D.getDeclSpec().isInlineSpecified();
|
||||
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
|
||||
bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();
|
||||
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
|
||||
ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
|
||||
isFriend = D.getDeclSpec().isFriendSpecified();
|
||||
if (isFriend && !isInline && D.isFunctionDefinition()) {
|
||||
// C++ [class.friend]p5
|
||||
|
@ -8621,7 +8629,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
}
|
||||
|
||||
if (isConstexpr) {
|
||||
if (ConstexprKind != CSK_unspecified) {
|
||||
// C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors
|
||||
// are implicitly inline.
|
||||
NewFD->setImplicitlyInline();
|
||||
|
@ -8630,7 +8638,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// be either constructors or to return a literal type. Therefore,
|
||||
// destructors cannot be declared constexpr.
|
||||
if (isa<CXXDestructorDecl>(NewFD))
|
||||
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
|
||||
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor)
|
||||
<< (ConstexprKind == CSK_consteval);
|
||||
}
|
||||
|
||||
// If __module_private__ was specified, mark the function accordingly.
|
||||
|
@ -9527,6 +9536,7 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
|
|||
DeletedFuncs = 5,
|
||||
DefaultedFuncs = 6,
|
||||
ConstexprFuncs = 7,
|
||||
ConstevalFuncs = 8,
|
||||
};
|
||||
enum Different {
|
||||
CallingConv = 0,
|
||||
|
@ -9602,7 +9612,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
|
|||
if (NewFD->isConstexpr() && (MVType == MultiVersionKind::CPUDispatch ||
|
||||
MVType == MultiVersionKind::CPUSpecific))
|
||||
return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
|
||||
<< IsCPUSpecificCPUDispatchMVType << ConstexprFuncs;
|
||||
<< IsCPUSpecificCPUDispatchMVType
|
||||
<< (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
|
||||
|
||||
QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType());
|
||||
const auto *NewType = cast<FunctionType>(NewQType);
|
||||
|
@ -9633,7 +9644,7 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
|
|||
return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
|
||||
<< ReturnType;
|
||||
|
||||
if (OldFD->isConstexpr() != NewFD->isConstexpr())
|
||||
if (OldFD->getConstexprKind() != NewFD->getConstexprKind())
|
||||
return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
|
||||
<< ConstexprSpec;
|
||||
|
||||
|
@ -10383,8 +10394,9 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
|
|||
}
|
||||
if (FD->isConstexpr()) {
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
|
||||
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
|
||||
FD->setConstexpr(false);
|
||||
<< FD->isConsteval()
|
||||
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
|
||||
FD->setConstexprKind(CSK_unspecified);
|
||||
}
|
||||
|
||||
if (getLangOpts().OpenCL) {
|
||||
|
@ -12475,9 +12487,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
|
|||
if (DS.isInlineSpecified())
|
||||
Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)
|
||||
<< getLangOpts().CPlusPlus17;
|
||||
if (DS.isConstexprSpecified())
|
||||
if (DS.hasConstexprSpecifier())
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
|
||||
<< 0;
|
||||
<< 0 << (D.getDeclSpec().getConstexprSpecifier() == CSK_consteval);
|
||||
|
||||
DiagnoseFunctionSpecifiers(DS);
|
||||
|
||||
|
@ -13128,7 +13140,7 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
|
|||
|
||||
bool Sema::canDelayFunctionBody(const Declarator &D) {
|
||||
// We can't delay parsing the body of a constexpr function template (yet).
|
||||
if (D.getDeclSpec().isConstexprSpecified())
|
||||
if (D.getDeclSpec().hasConstexprSpecifier())
|
||||
return false;
|
||||
|
||||
// We can't delay parsing the body of a function template with a deduced
|
||||
|
|
|
@ -7460,12 +7460,10 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
|
|||
// FIXME: Mangling?
|
||||
// FIXME: Is the qualifier info correct?
|
||||
// FIXME: Is the DeclContext correct?
|
||||
NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
|
||||
Loc, Loc, DeclarationName(II),
|
||||
FD->getType(), FD->getTypeSourceInfo(),
|
||||
SC_None, false/*isInlineSpecified*/,
|
||||
FD->hasPrototype(),
|
||||
false/*isConstexprSpecified*/);
|
||||
NewFD = FunctionDecl::Create(
|
||||
FD->getASTContext(), FD->getDeclContext(), Loc, Loc,
|
||||
DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None,
|
||||
false /*isInlineSpecified*/, FD->hasPrototype(), CSK_unspecified);
|
||||
NewD = NewFD;
|
||||
|
||||
if (FD->getQualifier())
|
||||
|
|
|
@ -638,9 +638,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
|
|||
// C++11 [dcl.constexpr]p1: If any declaration of a function or function
|
||||
// template has a constexpr specifier then all its declarations shall
|
||||
// contain the constexpr specifier.
|
||||
if (New->isConstexpr() != Old->isConstexpr()) {
|
||||
if (New->getConstexprKind() != Old->getConstexprKind()) {
|
||||
Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
|
||||
<< New << New->isConstexpr();
|
||||
<< New << New->getConstexprKind() << Old->getConstexprKind();
|
||||
Diag(Old->getLocation(), diag::note_previous_declaration);
|
||||
Invalid = true;
|
||||
} else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
|
||||
|
@ -741,8 +741,9 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
|
|||
CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(TSCS));
|
||||
CPlusPlus20SpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc());
|
||||
}
|
||||
if (DS.isConstexprSpecified()) {
|
||||
BadSpecifiers.push_back("constexpr");
|
||||
if (DS.hasConstexprSpecifier()) {
|
||||
BadSpecifiers.push_back(
|
||||
DeclSpec::getSpecifierName(DS.getConstexprSpecifier()));
|
||||
BadSpecifierLocs.push_back(DS.getConstexprSpecLoc());
|
||||
}
|
||||
if (DS.isInlineSpecified()) {
|
||||
|
@ -1581,10 +1582,10 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
|
|||
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
|
||||
SourceLocation ParamLoc = PD->getLocation();
|
||||
if (!(*i)->isDependentType() &&
|
||||
SemaRef.RequireLiteralType(ParamLoc, *i,
|
||||
diag::err_constexpr_non_literal_param,
|
||||
ArgIndex+1, PD->getSourceRange(),
|
||||
isa<CXXConstructorDecl>(FD)))
|
||||
SemaRef.RequireLiteralType(
|
||||
ParamLoc, *i, diag::err_constexpr_non_literal_param, ArgIndex + 1,
|
||||
PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
|
||||
FD->isConsteval()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1661,7 +1662,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
|
|||
QualType RT = NewFD->getReturnType();
|
||||
if (!RT->isDependentType() &&
|
||||
RequireLiteralType(NewFD->getLocation(), RT,
|
||||
diag::err_constexpr_non_literal_return))
|
||||
diag::err_constexpr_non_literal_return,
|
||||
NewFD->isConsteval()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1775,7 +1777,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
|
|||
|
||||
default:
|
||||
SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1960,7 +1962,7 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
|
|||
}
|
||||
|
||||
SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
|
||||
<< isa<CXXConstructorDecl>(Dcl);
|
||||
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2082,7 +2084,8 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
|
|||
Dcl->getReturnType()->isDependentType());
|
||||
Diag(Dcl->getLocation(),
|
||||
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
|
||||
: diag::err_constexpr_body_no_return);
|
||||
: diag::err_constexpr_body_no_return)
|
||||
<< Dcl->isConsteval();
|
||||
if (!OK)
|
||||
return false;
|
||||
} else if (ReturnStmts.size() > 1) {
|
||||
|
@ -3052,7 +3055,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
|
||||
!isFunc);
|
||||
|
||||
if (DS.isConstexprSpecified() && isInstField) {
|
||||
if (DS.hasConstexprSpecifier() && isInstField) {
|
||||
SemaDiagnosticBuilder B =
|
||||
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
|
||||
SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
|
||||
|
@ -6688,7 +6691,10 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
|
|||
: isa<CXXConstructorDecl>(MD)) &&
|
||||
MD->isConstexpr() && !Constexpr &&
|
||||
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
|
||||
Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM;
|
||||
Diag(MD->getBeginLoc(), MD->isConsteval()
|
||||
? diag::err_incorrect_defaulted_consteval
|
||||
: diag::err_incorrect_defaulted_constexpr)
|
||||
<< CSM;
|
||||
// FIXME: Explain why the special member can't be constexpr.
|
||||
HadError = true;
|
||||
}
|
||||
|
@ -6698,7 +6704,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
|
|||
// If a function is explicitly defaulted on its first declaration, it is
|
||||
// implicitly considered to be constexpr if the implicit declaration
|
||||
// would be.
|
||||
MD->setConstexpr(Constexpr);
|
||||
MD->setConstexprKind(Constexpr ? CSK_constexpr : CSK_unspecified);
|
||||
|
||||
if (!Type->hasExceptionSpec()) {
|
||||
// C++2a [except.spec]p3:
|
||||
|
@ -8744,7 +8750,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
|
|||
// We leave 'friend' and 'virtual' to be rejected in the normal way.
|
||||
if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() ||
|
||||
DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() ||
|
||||
DS.isNoreturnSpecified() || DS.isConstexprSpecified()) {
|
||||
DS.isNoreturnSpecified() || DS.hasConstexprSpecifier()) {
|
||||
BadSpecifierDiagnoser Diagnoser(
|
||||
*this, D.getIdentifierLoc(),
|
||||
diag::err_deduction_guide_invalid_specifier);
|
||||
|
@ -11035,7 +11041,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
|
|||
CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
|
||||
Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(),
|
||||
/*TInfo=*/nullptr, ExplicitSpecifier(),
|
||||
/*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr);
|
||||
/*isInline=*/true, /*isImplicitlyDeclared=*/true,
|
||||
Constexpr ? CSK_constexpr : CSK_unspecified);
|
||||
DefaultCon->setAccess(AS_public);
|
||||
DefaultCon->setDefaulted();
|
||||
|
||||
|
@ -11155,7 +11162,8 @@ Sema::findInheritingConstructor(SourceLocation Loc,
|
|||
CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create(
|
||||
Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
|
||||
BaseCtor->getExplicitSpecifier(), /*Inline=*/true,
|
||||
/*ImplicitlyDeclared=*/true, Constexpr,
|
||||
/*ImplicitlyDeclared=*/true,
|
||||
Constexpr ? BaseCtor->getConstexprKind() : CSK_unspecified,
|
||||
InheritedConstructor(Shadow, BaseCtor));
|
||||
if (Shadow->isInvalidDecl())
|
||||
DerivedCtor->setInvalidDecl();
|
||||
|
@ -11904,10 +11912,11 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
|
|||
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
|
||||
SourceLocation ClassLoc = ClassDecl->getLocation();
|
||||
DeclarationNameInfo NameInfo(Name, ClassLoc);
|
||||
CXXMethodDecl *CopyAssignment =
|
||||
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
|
||||
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
|
||||
/*isInline=*/true, Constexpr, SourceLocation());
|
||||
CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(
|
||||
Context, ClassDecl, ClassLoc, NameInfo, QualType(),
|
||||
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
|
||||
/*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified,
|
||||
SourceLocation());
|
||||
CopyAssignment->setAccess(AS_public);
|
||||
CopyAssignment->setDefaulted();
|
||||
CopyAssignment->setImplicit();
|
||||
|
@ -12224,10 +12233,11 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
|
|||
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
|
||||
SourceLocation ClassLoc = ClassDecl->getLocation();
|
||||
DeclarationNameInfo NameInfo(Name, ClassLoc);
|
||||
CXXMethodDecl *MoveAssignment =
|
||||
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
|
||||
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
|
||||
/*isInline=*/true, Constexpr, SourceLocation());
|
||||
CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create(
|
||||
Context, ClassDecl, ClassLoc, NameInfo, QualType(),
|
||||
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
|
||||
/*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified,
|
||||
SourceLocation());
|
||||
MoveAssignment->setAccess(AS_public);
|
||||
MoveAssignment->setDefaulted();
|
||||
MoveAssignment->setImplicit();
|
||||
|
@ -12608,7 +12618,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
|
|||
Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
|
||||
ExplicitSpecifier(),
|
||||
/*isInline=*/true,
|
||||
/*isImplicitlyDeclared=*/true, Constexpr);
|
||||
/*isImplicitlyDeclared=*/true,
|
||||
Constexpr ? CSK_constexpr : CSK_unspecified);
|
||||
CopyConstructor->setAccess(AS_public);
|
||||
CopyConstructor->setDefaulted();
|
||||
|
||||
|
@ -12739,7 +12750,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
|
|||
Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
|
||||
ExplicitSpecifier(),
|
||||
/*isInline=*/true,
|
||||
/*isImplicitlyDeclared=*/true, Constexpr);
|
||||
/*isImplicitlyDeclared=*/true,
|
||||
Constexpr ? CSK_constexpr : CSK_unspecified);
|
||||
MoveConstructor->setAccess(AS_public);
|
||||
MoveConstructor->setDefaulted();
|
||||
|
||||
|
|
|
@ -17125,13 +17125,11 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
|
|||
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
|
||||
if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) {
|
||||
SourceLocation Loc = FD->getLocation();
|
||||
FunctionDecl *NewFD = FunctionDecl::Create(S.Context,
|
||||
FD->getDeclContext(),
|
||||
Loc, Loc, FD->getNameInfo().getName(),
|
||||
DestType, FD->getTypeSourceInfo(),
|
||||
SC_None, false/*isInlineSpecified*/,
|
||||
FD->hasPrototype(),
|
||||
false/*isConstexprSpecified*/);
|
||||
FunctionDecl *NewFD = FunctionDecl::Create(
|
||||
S.Context, FD->getDeclContext(), Loc, Loc,
|
||||
FD->getNameInfo().getName(), DestType, FD->getTypeSourceInfo(),
|
||||
SC_None, false /*isInlineSpecified*/, FD->hasPrototype(),
|
||||
/*ConstexprKind*/ CSK_unspecified);
|
||||
|
||||
if (FD->getQualifier())
|
||||
NewFD->setQualifierInfo(FD->getQualifierLoc());
|
||||
|
|
|
@ -370,7 +370,7 @@ Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext(
|
|||
CXXMethodDecl *Sema::startLambdaDefinition(
|
||||
CXXRecordDecl *Class, SourceRange IntroducerRange,
|
||||
TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc,
|
||||
ArrayRef<ParmVarDecl *> Params, const bool IsConstexprSpecified,
|
||||
ArrayRef<ParmVarDecl *> Params, ConstexprSpecKind ConstexprKind,
|
||||
Optional<std::pair<unsigned, Decl *>> Mangling) {
|
||||
QualType MethodType = MethodTypeInfo->getType();
|
||||
TemplateParameterList *TemplateParams =
|
||||
|
@ -400,16 +400,12 @@ CXXMethodDecl *Sema::startLambdaDefinition(
|
|||
= IntroducerRange.getBegin().getRawEncoding();
|
||||
MethodNameLoc.CXXOperatorName.EndOpNameLoc
|
||||
= IntroducerRange.getEnd().getRawEncoding();
|
||||
CXXMethodDecl *Method
|
||||
= CXXMethodDecl::Create(Context, Class, EndLoc,
|
||||
DeclarationNameInfo(MethodName,
|
||||
IntroducerRange.getBegin(),
|
||||
MethodNameLoc),
|
||||
MethodType, MethodTypeInfo,
|
||||
SC_None,
|
||||
/*isInline=*/true,
|
||||
IsConstexprSpecified,
|
||||
EndLoc);
|
||||
CXXMethodDecl *Method = CXXMethodDecl::Create(
|
||||
Context, Class, EndLoc,
|
||||
DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
|
||||
MethodNameLoc),
|
||||
MethodType, MethodTypeInfo, SC_None,
|
||||
/*isInline=*/true, ConstexprKind, EndLoc);
|
||||
Method->setAccess(AS_public);
|
||||
|
||||
// Temporarily set the lexical declaration context to the current
|
||||
|
@ -940,7 +936,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
|||
|
||||
CXXMethodDecl *Method =
|
||||
startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params,
|
||||
ParamInfo.getDeclSpec().isConstexprSpecified());
|
||||
ParamInfo.getDeclSpec().getConstexprSpecifier());
|
||||
if (ExplicitParams)
|
||||
CheckCXXDefaultArguments(Method);
|
||||
|
||||
|
@ -1341,7 +1337,7 @@ static void addFunctionPointerConversion(Sema &S,
|
|||
S.Context, Class, Loc,
|
||||
DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI,
|
||||
/*isInline=*/true, ExplicitSpecifier(),
|
||||
/*isConstexpr=*/S.getLangOpts().CPlusPlus17,
|
||||
S.getLangOpts().CPlusPlus17 ? CSK_constexpr : CSK_unspecified,
|
||||
CallOperator->getBody()->getEndLoc());
|
||||
Conversion->setAccess(AS_public);
|
||||
Conversion->setImplicit(true);
|
||||
|
@ -1380,8 +1376,7 @@ static void addFunctionPointerConversion(Sema &S,
|
|||
CXXMethodDecl *Invoke = CXXMethodDecl::Create(
|
||||
S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc),
|
||||
InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static,
|
||||
/*IsInline=*/true,
|
||||
/*IsConstexpr=*/false, CallOperator->getBody()->getEndLoc());
|
||||
/*IsInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc());
|
||||
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
|
||||
InvokerParams[I]->setOwningFunction(Invoke);
|
||||
Invoke->setParams(InvokerParams);
|
||||
|
@ -1427,8 +1422,8 @@ static void addBlockPointerConversion(Sema &S,
|
|||
CXXConversionDecl *Conversion = CXXConversionDecl::Create(
|
||||
S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy,
|
||||
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
|
||||
/*isInline=*/true, ExplicitSpecifier(),
|
||||
/*isConstexpr=*/false, CallOperator->getBody()->getEndLoc());
|
||||
/*isInline=*/true, ExplicitSpecifier(), CSK_unspecified,
|
||||
CallOperator->getBody()->getEndLoc());
|
||||
Conversion->setAccess(AS_public);
|
||||
Conversion->setImplicit(true);
|
||||
Class->addDecl(Conversion);
|
||||
|
@ -1782,9 +1777,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
|
|||
!isa<CoroutineBodyStmt>(CallOperator->getBody()) &&
|
||||
!Class->getDeclContext()->isDependentContext()) {
|
||||
TentativeAnalysisScope DiagnosticScopeGuard(*this);
|
||||
CallOperator->setConstexpr(
|
||||
CheckConstexprFunctionDecl(CallOperator) &&
|
||||
CheckConstexprFunctionBody(CallOperator, CallOperator->getBody()));
|
||||
CallOperator->setConstexprKind(
|
||||
(CheckConstexprFunctionDecl(CallOperator) &&
|
||||
CheckConstexprFunctionBody(CallOperator, CallOperator->getBody()))
|
||||
? CSK_constexpr
|
||||
: CSK_unspecified);
|
||||
}
|
||||
|
||||
// Emit delayed shadowing warnings now that the full capture list is known.
|
||||
|
|
|
@ -3693,7 +3693,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
|
|||
}
|
||||
|
||||
if (FD)
|
||||
Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/;
|
||||
Diag(ReturnLoc, DiagID)
|
||||
<< FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval();
|
||||
else
|
||||
Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
|
||||
|
||||
|
|
|
@ -1147,7 +1147,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
|||
// variable or variable template or the declaration of a function or
|
||||
// function template.
|
||||
|
||||
if (DS.isConstexprSpecified())
|
||||
if (DS.hasConstexprSpecifier())
|
||||
EmitDiag(DS.getConstexprSpecLoc());
|
||||
|
||||
// [dcl.fct.spec]p1:
|
||||
|
@ -8371,7 +8371,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
|
|||
// FIXME: We need an update record for this AST mutation.
|
||||
// FIXME: What if there are multiple such prior declarations (for instance,
|
||||
// from different modules)?
|
||||
Specialization->setConstexpr(FD->isConstexpr());
|
||||
Specialization->setConstexprKind(FD->getConstexprKind());
|
||||
}
|
||||
|
||||
// FIXME: Check if the prior specialization has a point of instantiation.
|
||||
|
@ -9260,7 +9260,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
diag::err_explicit_instantiation_inline :
|
||||
diag::warn_explicit_instantiation_inline_0x)
|
||||
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
|
||||
if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType())
|
||||
if (D.getDeclSpec().hasConstexprSpecifier() && R->isFunctionType())
|
||||
// FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
|
||||
// not already specified.
|
||||
Diag(D.getDeclSpec().getConstexprSpecLoc(),
|
||||
|
|
|
@ -1779,7 +1779,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
Function = FunctionDecl::Create(
|
||||
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
|
||||
D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(),
|
||||
D->hasWrittenPrototype(), D->isConstexpr());
|
||||
D->hasWrittenPrototype(), D->getConstexprKind());
|
||||
Function->setRangeEnd(D->getSourceRange().getEnd());
|
||||
}
|
||||
|
||||
|
@ -2087,7 +2087,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
Method = CXXConstructorDecl::Create(
|
||||
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
|
||||
InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false,
|
||||
Constructor->isConstexpr());
|
||||
Constructor->getConstexprKind());
|
||||
Method->setRangeEnd(Constructor->getEndLoc());
|
||||
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
|
||||
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
|
||||
|
@ -2099,12 +2099,12 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
Method = CXXConversionDecl::Create(
|
||||
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
|
||||
Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier,
|
||||
Conversion->isConstexpr(), Conversion->getEndLoc());
|
||||
Conversion->getConstexprKind(), Conversion->getEndLoc());
|
||||
} else {
|
||||
StorageClass SC = D->isStatic() ? SC_Static : SC_None;
|
||||
Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo,
|
||||
T, TInfo, SC, D->isInlineSpecified(),
|
||||
D->isConstexpr(), D->getEndLoc());
|
||||
D->getConstexprKind(), D->getEndLoc());
|
||||
}
|
||||
|
||||
if (D->isInlined())
|
||||
|
|
|
@ -5146,7 +5146,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
// C++0x [dcl.constexpr]p9:
|
||||
// A constexpr specifier used in an object declaration declares the object
|
||||
// as const.
|
||||
if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
|
||||
if (D.getDeclSpec().hasConstexprSpecifier() && T->isObjectType()) {
|
||||
T.addConst();
|
||||
}
|
||||
|
||||
|
|
|
@ -11337,7 +11337,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
|
|||
Class, E->getIntroducerRange(), NewCallOpTSI,
|
||||
E->getCallOperator()->getEndLoc(),
|
||||
NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
|
||||
E->getCallOperator()->isConstexpr(), Mangling);
|
||||
E->getCallOperator()->getConstexprKind(), Mangling);
|
||||
|
||||
LSI->CallOperator = NewCallOperator;
|
||||
|
||||
|
|
|
@ -868,7 +868,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
FD->setDefaulted(Record.readInt());
|
||||
FD->setExplicitlyDefaulted(Record.readInt());
|
||||
FD->setHasImplicitReturnZero(Record.readInt());
|
||||
FD->setConstexpr(Record.readInt());
|
||||
FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt()));
|
||||
FD->setUsesSEHTry(Record.readInt());
|
||||
FD->setHasSkippedBody(Record.readInt());
|
||||
FD->setIsMultiVersion(Record.readInt());
|
||||
|
|
|
@ -545,7 +545,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
Record.push_back(D->isDefaulted());
|
||||
Record.push_back(D->isExplicitlyDefaulted());
|
||||
Record.push_back(D->hasImplicitReturnZero());
|
||||
Record.push_back(D->isConstexpr());
|
||||
Record.push_back(D->getConstexprKind());
|
||||
Record.push_back(D->usesSEHTry());
|
||||
Record.push_back(D->hasSkippedBody());
|
||||
Record.push_back(D->isMultiVersion());
|
||||
|
|
|
@ -56,4 +56,13 @@ struct C {
|
|||
#if !defined(__cpp_conditional_explicit) || __cpp_conditional_explicit != 201806L
|
||||
#error "the feature test macro __cpp_conditional_explicit isn't correct"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
auto l = []() consteval {};
|
||||
int consteval();
|
||||
#if __cplusplus <= 201703L
|
||||
// expected-warning@-3 {{'consteval' is a keyword in C++2a}}
|
||||
// expected-error@-4 {{expected body of lambda expression}}
|
||||
#else
|
||||
// expected-error@-5 {{expected unqualified-id}}
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify
|
||||
|
||||
namespace basic_sema {
|
||||
|
||||
consteval int f1(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
consteval constexpr int f2(int i) {
|
||||
//expected-error@-1 {{cannot combine}}
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr auto l_eval = [](int i) consteval {
|
||||
|
||||
return i;
|
||||
};
|
||||
|
||||
constexpr consteval int f3(int i) {
|
||||
//expected-error@-1 {{cannot combine}}
|
||||
return i;
|
||||
}
|
||||
|
||||
struct A {
|
||||
consteval int f1(int i) const {
|
||||
return i;
|
||||
}
|
||||
consteval A(int i);
|
||||
consteval A() = default;
|
||||
consteval ~A() = default; // expected-error {{destructor cannot be marked consteval}}
|
||||
};
|
||||
|
||||
consteval struct B {}; // expected-error {{struct cannot be marked consteval}}
|
||||
|
||||
consteval typedef B b; // expected-error {{typedef cannot be consteval}}
|
||||
|
||||
consteval int redecl() {return 0;} // expected-note {{previous declaration is here}}
|
||||
constexpr int redecl() {return 0;} // expected-error {{constexpr declaration of 'redecl' follows consteval declaration}}
|
||||
|
||||
consteval int i = 0; // expected-error {{consteval can only be used in function declarations}}
|
||||
|
||||
consteval int; // expected-error {{consteval can only be used in function declarations}}
|
||||
|
||||
consteval int f1() {} // expected-error {{no return statement in consteval function}}
|
||||
|
||||
struct C {
|
||||
C() {}
|
||||
};
|
||||
|
||||
struct D {
|
||||
C c;
|
||||
consteval D() = default; // expected-error {{cannot be consteval}}
|
||||
};
|
||||
}
|
||||
|
||||
consteval int main() { // expected-error {{'main' is not allowed to be declared consteval}}
|
||||
return 0;
|
||||
}
|
|
@ -2127,7 +2127,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
|
|||
clang::FunctionDecl *func_decl = FunctionDecl::Create(
|
||||
*ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
|
||||
nullptr, SC_Extern, isInlineSpecified, hasWrittenPrototype,
|
||||
isConstexprSpecified);
|
||||
isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
|
||||
|
||||
// We have to do more than just synthesize the FunctionDecl. We have to
|
||||
// synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
|
||||
|
|
|
@ -2170,7 +2170,7 @@ FunctionDecl *ClangASTContext::CreateFunctionDeclaration(
|
|||
*ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName,
|
||||
ClangUtil::GetQualType(function_clang_type), nullptr,
|
||||
(clang::StorageClass)storage, is_inline, hasWrittenPrototype,
|
||||
isConstexprSpecified);
|
||||
isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
|
||||
if (func_decl)
|
||||
decl_ctx->addDecl(func_decl);
|
||||
|
||||
|
@ -8210,7 +8210,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
|
|||
clang::SourceLocation()),
|
||||
method_qual_type,
|
||||
nullptr, // TypeSourceInfo *
|
||||
explicit_spec, is_inline, is_artificial, false /*is_constexpr*/);
|
||||
explicit_spec, is_inline, is_artificial, CSK_unspecified);
|
||||
cxx_method_decl = cxx_ctor_decl;
|
||||
} else {
|
||||
clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
|
||||
|
@ -8233,7 +8233,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
|
|||
clang::SourceLocation()),
|
||||
method_qual_type,
|
||||
nullptr, // TypeSourceInfo *
|
||||
SC, is_inline, false /*is_constexpr*/, clang::SourceLocation());
|
||||
SC, is_inline, CSK_unspecified, clang::SourceLocation());
|
||||
} else if (num_params == 0) {
|
||||
// Conversion operators don't take params...
|
||||
cxx_method_decl = clang::CXXConversionDecl::Create(
|
||||
|
@ -8245,7 +8245,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
|
|||
clang::SourceLocation()),
|
||||
method_qual_type,
|
||||
nullptr, // TypeSourceInfo *
|
||||
is_inline, explicit_spec, false /*is_constexpr*/,
|
||||
is_inline, explicit_spec, CSK_unspecified,
|
||||
clang::SourceLocation());
|
||||
}
|
||||
}
|
||||
|
@ -8256,7 +8256,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
|
|||
clang::DeclarationNameInfo(decl_name, clang::SourceLocation()),
|
||||
method_qual_type,
|
||||
nullptr, // TypeSourceInfo *
|
||||
SC, is_inline, false /*is_constexpr*/, clang::SourceLocation());
|
||||
SC, is_inline, CSK_unspecified, clang::SourceLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue