/// that was defined in the class body.
bool isInlined() const { return FunctionDeclBits.IsInline; }
+ /// Whether this function is marked as explicit explicitly.
+ bool isExplicitSpecified() const {
+ return FunctionDeclBits.IsExplicitSpecified;
+ }
+
+ /// State that this function is marked as explicit explicitly.
+ void setExplicitSpecified(bool ExpSpec = true) {
+ FunctionDeclBits.IsExplicitSpecified = ExpSpec;
+ }
+
bool isInlineDefinitionExternallyVisible() const;
bool isMSExternInline() const;
uint64_t IsInline : 1;
uint64_t IsInlineSpecified : 1;
+ /// This is shared by CXXConstructorDecl,
+ /// CXXConversionDecl, and CXXDeductionGuideDecl.
+ uint64_t IsExplicitSpecified : 1;
+
uint64_t IsVirtualAsWritten : 1;
uint64_t IsPure : 1;
uint64_t HasInheritedPrototype : 1;
};
/// 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
/// For the bits in FunctionDeclBitfields.
uint64_t : NumFunctionDeclBits;
- /// 24 bits to fit in the remaining available space.
+ /// 25 bits to fit in the remaining availible space.
/// Note that this makes CXXConstructorDeclBitfields take
/// 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 : 25;
uint64_t IsInheritingConstructor : 1;
-
- /// Whether this constructor has a trail-allocated explicit specifier.
- uint64_t HasTrailingExplicitSpecifier : 1;
- /// If this constructor does't have a trail-allocated explicit specifier.
- /// Whether this constructor is explicit specified.
- uint64_t IsSimpleExplicit : 1;
};
/// Number of non-inherited bits in CXXConstructorDeclBitfields.
- enum {
- NumCXXConstructorDeclBits = 64 - NumDeclContextBits - NumFunctionDeclBits
- };
+ enum { NumCXXConstructorDeclBits = 26 };
/// Stores the bits used by ObjCMethodDecl.
/// If modified NumObjCMethodDeclBits and the accessor
}
};
-/// Store information needed for an explicit specifier.
-/// used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl.
-class ExplicitSpecifier {
- llvm::PointerIntPair<Expr *, 2, ExplicitSpecKind> ExplicitSpec{
- nullptr, ExplicitSpecKind::ResolvedFalse};
-
-public:
- ExplicitSpecifier() = default;
- ExplicitSpecifier(Expr *Expression, ExplicitSpecKind Kind)
- : ExplicitSpec(Expression, Kind) {}
- ExplicitSpecKind getKind() const { return ExplicitSpec.getInt(); }
- const Expr *getExpr() const { return ExplicitSpec.getPointer(); }
- Expr *getExpr() { return ExplicitSpec.getPointer(); }
-
- /// Return true if the ExplicitSpecifier isn't defaulted.
- bool isSpecified() const {
- return ExplicitSpec.getInt() != ExplicitSpecKind::ResolvedFalse ||
- ExplicitSpec.getPointer();
- }
-
- /// Check for Equivalence of explicit specifiers.
- /// Return True if the explicit specifier are equivalent false otherwise.
- bool isEquivalent(const ExplicitSpecifier Other) const;
- /// Return true if the explicit specifier is already resolved to be explicit.
- bool isExplicit() const {
- return ExplicitSpec.getInt() == ExplicitSpecKind::ResolvedTrue;
- }
- /// Return true if the ExplicitSpecifier isn't valid.
- /// This state occurs after a substitution failures.
- bool isInvalid() const {
- return ExplicitSpec.getInt() == ExplicitSpecKind::Unresolved &&
- !ExplicitSpec.getPointer();
- }
- void setKind(ExplicitSpecKind Kind) { ExplicitSpec.setInt(Kind); }
- void setExpr(Expr *E) { ExplicitSpec.setPointer(E); }
- // getFromDecl - retrieve the explicit specifier in the given declaration.
- // if the given declaration has no explicit. the returned explicit specifier
- // is defaulted. .isSpecified() will be false.
- static ExplicitSpecifier getFromDecl(FunctionDecl *Function);
- static ExplicitSpecifier Invalid() {
- return ExplicitSpecifier(nullptr, ExplicitSpecKind::Unresolved);
- }
-};
-
/// Represents a C++ deduction guide declaration.
///
/// \code
private:
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- ExplicitSpecifier ES,
- const DeclarationNameInfo &NameInfo, QualType T,
- TypeSourceInfo *TInfo, SourceLocation EndLocation)
+ bool IsExplicit, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ SourceLocation EndLocation)
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
- SC_None, false, false),
- ExplicitSpec(ES) {
+ SC_None, false, false) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
+ setExplicitSpecified(IsExplicit);
setIsCopyDeductionCandidate(false);
}
- ExplicitSpecifier ExplicitSpec;
- void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
-
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- static CXXDeductionGuideDecl *
- Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
- TypeSourceInfo *TInfo, SourceLocation EndLocation);
+ static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, bool IsExplicit,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ SourceLocation EndLocation);
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
- const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; }
-
- /// Return true if the declartion is already resolved to be explicit.
- bool isExplicit() const { return ExplicitSpec.isExplicit(); }
+ /// Whether this deduction guide is explicit.
+ bool isExplicit() const { return isExplicitSpecified(); }
/// Get the template for which this guide performs deduction.
TemplateDecl *getDeducedTemplate() const {
/// \endcode
class CXXConstructorDecl final
: public CXXMethodDecl,
- private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor,
- ExplicitSpecifier> {
+ private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> {
// This class stores some data in DeclContext::CXXConstructorDeclBits
// to save some space. Use the provided accessors to access it.
LazyCXXCtorInitializersPtr CtorInitializers;
CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo, QualType T,
- TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared, bool isConstexpr,
InheritedConstructor Inherited);
void anchor() override;
- size_t numTrailingObjects(OverloadToken<InheritedConstructor>) const {
- return CXXConstructorDeclBits.IsInheritingConstructor;
- }
- size_t numTrailingObjects(OverloadToken<ExplicitSpecifier>) const {
- return CXXConstructorDeclBits.HasTrailingExplicitSpecifier;
- }
-
- ExplicitSpecifier getExplicitSpecifierInternal() const {
- if (CXXConstructorDeclBits.HasTrailingExplicitSpecifier)
- return *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>();
- return ExplicitSpecifier(
- nullptr, getCanonicalDecl()->CXXConstructorDeclBits.IsSimpleExplicit
- ? ExplicitSpecKind::ResolvedTrue
- : ExplicitSpecKind::ResolvedFalse);
- }
-
- void setExplicitSpecifier(ExplicitSpecifier ES) {
- assert((!ES.getExpr() ||
- CXXConstructorDeclBits.HasTrailingExplicitSpecifier) &&
- "cannot set this explicit specifier. no trail-allocated space for "
- "explicit");
- if (ES.getExpr())
- *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES;
- else
- CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit();
- }
-
- enum TraillingAllocKind {
- TAKInheritsConstructor = 1,
- TAKHasTailExplicit = 1 << 1,
- };
-
- uint64_t getTraillingAllocKind() const {
- return numTrailingObjects(OverloadToken<InheritedConstructor>()) |
- (numTrailingObjects(OverloadToken<ExplicitSpecifier>()) << 1);
- }
-
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend TrailingObjects;
static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID,
- uint64_t AllocKind);
+ bool InheritsConstructor);
static CXXConstructorDecl *
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
+ bool isExplicit, bool isInline, bool isImplicitlyDeclared,
bool isConstexpr,
InheritedConstructor Inherited = InheritedConstructor());
- ExplicitSpecifier getExplicitSpecifier() {
- return getExplicitSpecifierInternal();
- }
- const ExplicitSpecifier getExplicitSpecifier() const {
- return getExplicitSpecifierInternal();
- }
-
- /// Return true if the declartion is already resolved to be explicit.
- bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
-
/// Iterates through the member/base initializer list.
using init_iterator = CXXCtorInitializer **;
CtorInitializers = Initializers;
}
+ /// Whether this function is explicit.
+ bool isExplicit() const {
+ return getCanonicalDecl()->isExplicitSpecified();
+ }
+
/// Determine whether this constructor is a delegating constructor.
bool isDelegatingConstructor() const {
return (getNumCtorInitializers() == 1) &&
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)
+ TypeSourceInfo *TInfo, bool isInline,
+ bool isExplicitSpecified, bool isConstexpr,
+ SourceLocation EndLocation)
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
- SC_None, isInline, isConstexpr, EndLocation),
- ExplicitSpec(ES) {}
- void anchor() override;
-
- ExplicitSpecifier ExplicitSpec;
+ SC_None, isInline, isConstexpr, EndLocation) {
+ setExplicitSpecified(isExplicitSpecified);
+ }
- void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
+ void anchor() override;
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
- static CXXConversionDecl *
- Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- bool isInline, ExplicitSpecifier ES, bool isConstexpr,
- SourceLocation EndLocation);
+ static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicit,
+ bool isConstexpr,
+ SourceLocation EndLocation);
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- ExplicitSpecifier getExplicitSpecifier() {
- return getCanonicalDecl()->ExplicitSpec;
- }
-
- const ExplicitSpecifier getExplicitSpecifier() const {
- return getCanonicalDecl()->ExplicitSpec;
+ /// Whether this function is explicit.
+ bool isExplicit() const {
+ return getCanonicalDecl()->isExplicitSpecified();
}
- /// Return true if the declartion is already resolved to be explicit.
- bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
-
/// Returns the type that this conversion function is converting to.
QualType getConversionType() const {
return getType()->getAs<FunctionType>()->getReturnType();
AST_POLYMORPHIC_MATCHER(isExplicit,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl,
CXXConversionDecl)) {
- // FIXME : it's not clear whether this should match a dependent
- // explicit(....). this matcher should also be able to match
- // CXXDeductionGuideDecl with explicit specifier.
return Node.isExplicit();
}
def warn_duplicate_declspec : Warning<"%sub{duplicate_declspec}0">,
InGroup<DuplicateDeclSpecifier>;
-def err_duplicate_declspec : Error<"%sub{duplicate_declspec}0">;
-
def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
def err_invalid_member_in_interface : Error<
let CategoryName = "Parse Issue" in {
-def warn_cxx2a_compat_explicit_bool : Warning<
- "this expression will be parsed as explicit(bool) in C++2a">,
- InGroup<CXX2aCompat>, DefaultIgnore;
-
def ext_empty_translation_unit : Extension<
"ISO C requires a translation unit to contain at least one declaration">,
InGroup<DiagGroup<"empty-translation-unit">>;
"bind reference to a temporary">;
def err_expr_not_cce : Error<
"%select{case value|enumerator value|non-type template argument|"
- "array size|constexpr if condition|explicit specifier argument}0 "
+ "array size|constexpr if condition}0 "
"is not a constant expression">;
def ext_cce_narrowing : ExtWarn<
"%select{case value|enumerator value|non-type template argument|"
- "array size|constexpr if condition|explicit specifier argument}0 "
+ "array size|constexpr if condition}0 "
"%select{cannot be narrowed from type %2 to %3|"
"evaluates to %2, which cannot be narrowed to type %3}1">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
"deduction guide must be declared in the same scope as template %q0">;
def err_deduction_guide_defines_function : Error<
"deduction guide cannot have a function definition">;
-def err_deduction_guide_redeclared : Error<
- "redeclaration of deduction guide">;
+def err_deduction_guide_explicit_mismatch : Error<
+ "deduction guide is %select{not |}0declared 'explicit' but "
+ "previous declaration was%select{ not|}0">;
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
"%select{explicitly instantiated|explicitly specialized}0">;
def err_deduction_guide_template_not_deducible : Error<
"| has different qualifiers (expected %5 but found %6)"
"| has different exception specification}4">;
-def note_ovl_candidate_explicit_forbidden : Note<
- "candidate %0 ignored: cannot be explicit">;
-def note_explicit_bool_resolved_to_true : Note<
- "explicit(bool) specifier resolved to true">;
def note_ovl_candidate_inherited_constructor : Note<
"constructor from base class %0 inherited here">;
def note_ovl_candidate_inherited_constructor_slice : Note<
#include "llvm/Support/ErrorHandling.h"
namespace clang {
-
- /// Define the meaning of possible values of the kind in ExplicitSpecifier.
- enum class ExplicitSpecKind : unsigned {
- ResolvedFalse,
- ResolvedTrue,
- Unresolved,
- };
-
/// Specifies the width of a type, e.g., short, long, or long long.
enum TypeSpecifierWidth {
TSW_unspecified,
#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
#define LLVM_CLANG_SEMA_DECLSPEC_H
-#include "clang/AST/DeclCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/Lambda.h"
unsigned FS_inline_specified : 1;
unsigned FS_forceinline_specified: 1;
unsigned FS_virtual_specified : 1;
+ unsigned FS_explicit_specified : 1;
unsigned FS_noreturn_specified : 1;
// friend-specifier
Expr *ExprRep;
};
- /// ExplicitSpecifier - Store information about explicit spicifer.
- ExplicitSpecifier FS_explicit_specifier;
-
// attributes.
ParsedAttributes Attrs;
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc,
TQ_unalignedLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
- SourceLocation FS_explicitCloseParenLoc;
SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
SourceLocation TQ_pipeLoc;
}
DeclSpec(AttributeFactory &attrFactory)
- : StorageClassSpec(SCS_unspecified),
- ThreadStorageClassSpec(TSCS_unspecified),
- SCS_extern_in_linkage_spec(false), TypeSpecWidth(TSW_unspecified),
- TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified),
- TypeSpecType(TST_unspecified), TypeAltiVecVector(false),
- TypeAltiVecPixel(false), TypeAltiVecBool(false), TypeSpecOwned(false),
- 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),
- FS_explicit_specifier(), Attrs(attrFactory), writtenBS(),
- ObjCQualifiers(nullptr) {}
+ : StorageClassSpec(SCS_unspecified),
+ ThreadStorageClassSpec(TSCS_unspecified),
+ SCS_extern_in_linkage_spec(false),
+ TypeSpecWidth(TSW_unspecified),
+ TypeSpecComplex(TSC_unspecified),
+ TypeSpecSign(TSS_unspecified),
+ TypeSpecType(TST_unspecified),
+ TypeAltiVecVector(false),
+ TypeAltiVecPixel(false),
+ TypeAltiVecBool(false),
+ TypeSpecOwned(false),
+ TypeSpecPipe(false),
+ TypeSpecSat(false),
+ TypeQualifiers(TQ_unspecified),
+ FS_inline_specified(false),
+ FS_forceinline_specified(false),
+ FS_virtual_specified(false),
+ FS_explicit_specified(false),
+ FS_noreturn_specified(false),
+ Friend_specified(false),
+ Constexpr_specified(false),
+ Attrs(attrFactory),
+ writtenBS(),
+ ObjCQualifiers(nullptr) {
+ }
// storage-class-specifier
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc;
}
- ExplicitSpecifier getExplicitSpecifier() const {
- return FS_explicit_specifier;
- }
-
bool isVirtualSpecified() const { return FS_virtual_specified; }
SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
- bool hasExplicitSpecifier() const {
- return FS_explicit_specifier.isSpecified();
- }
+ bool isExplicitSpecified() const { return FS_explicit_specified; }
SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; }
- SourceRange getExplicitSpecRange() const {
- return FS_explicit_specifier.getExpr()
- ? SourceRange(FS_explicitLoc, FS_explicitCloseParenLoc)
- : SourceRange(FS_explicitLoc);
- }
bool isNoreturnSpecified() const { return FS_noreturn_specified; }
SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; }
FS_forceinlineLoc = SourceLocation();
FS_virtual_specified = false;
FS_virtualLoc = SourceLocation();
- FS_explicit_specifier = ExplicitSpecifier();
+ FS_explicit_specified = false;
FS_explicitLoc = SourceLocation();
- FS_explicitCloseParenLoc = SourceLocation();
FS_noreturn_specified = false;
FS_noreturnLoc = SourceLocation();
}
bool setFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
bool setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, ExplicitSpecifier ExplicitSpec,
- SourceLocation CloseParenLoc);
+ unsigned &DiagID);
bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
/// attribute disabled it.
ovl_fail_enable_if,
- /// This candidate constructor or conversion fonction
- /// is used implicitly but the explicit(bool) specifier
- /// was resolved to true
- ovl_fail_explicit_resolved,
-
/// This candidate was not viable because its address could not be taken.
ovl_fail_addr_not_available,
CCEK_Enumerator, ///< Enumerator value with fixed underlying type.
CCEK_TemplateArg, ///< Value of a non-type template parameter.
CCEK_NewExpr, ///< Constant expression in a noptr-new-declarator.
- CCEK_ConstexprIf, ///< Condition in a constexpr if statement.
- CCEK_ExplicitBool ///< Condition in an explicit(bool) specifier.
+ CCEK_ConstexprIf ///< Condition in a constexpr if statement.
};
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value, CCEKind CCE);
bool SuppressUserConversions = false,
bool PartialOverloading = false,
bool AllowExplicit = false,
- bool AllowExplicitConversion = false,
ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
ConversionSequenceList EarlyConversions = None);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
- bool PartialOverloading = false, bool AllowExplicit = false,
+ bool PartialOverloading = false,
ADLCallKind IsADLCandidate = ADLCallKind::NotADL);
bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
ArrayRef<QualType> ParamTypes,
QualType ObjectType = QualType(),
Expr::Classification
ObjectClassification = {});
- void AddConversionCandidate(
- CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
- bool AllowExplicit, bool AllowResultConversion = true);
- void AddTemplateConversionCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
- bool AllowExplicit, bool AllowResultConversion = true);
+ void AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion = true);
+ void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet,
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion = true);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E,
bool IsConstexpr = false);
- /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
- /// found in an explicit(bool) specifier.
- ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
-
- /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
- /// Returns true if the explicit specifier is now resolved.
- bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
-
/// DiagnoseAssignmentAsCondition - Given that an expression is
/// being used as a boolean condition, warn if it's an assignment.
void DiagnoseAssignmentAsCondition(Expr *E);
/// A CXXConstructorDecl record.
DECL_CXX_CONSTRUCTOR,
+ /// A CXXConstructorDecl record for an inherited constructor.
+ DECL_CXX_INHERITED_CONSTRUCTOR,
+
/// A CXXDestructorDecl record.
DECL_CXX_DESTRUCTOR,
ID);
}
- ExplicitSpecifier readExplicitSpec() {
- uint64_t Kind = readInt();
- bool HasExpr = Kind & 0x1;
- Kind = Kind >> 1;
- return ExplicitSpecifier(HasExpr ? readExpr() : nullptr,
- static_cast<ExplicitSpecKind>(Kind));
- }
-
void readExceptionSpec(SmallVectorImpl<QualType> &ExceptionStorage,
FunctionProtoType::ExceptionSpecInfo &ESI) {
return Reader->readExceptionSpec(*F, ExceptionStorage, ESI, Record, Idx);
// Create the imported function.
FunctionDecl *ToFunction = nullptr;
if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
- Expr *ExplicitExpr = nullptr;
- if (FromConstructor->getExplicitSpecifier().getExpr()) {
- auto Imp = importSeq(FromConstructor->getExplicitSpecifier().getExpr());
- if (!Imp)
- return Imp.takeError();
- std::tie(ExplicitExpr) = *Imp;
- }
if (GetImportedOrCreateDecl<CXXConstructorDecl>(
- ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
- ToInnerLocStart, NameInfo, T, TInfo,
- ExplicitSpecifier(
- ExplicitExpr,
- FromConstructor->getExplicitSpecifier().getKind()),
- D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ ToInnerLocStart, NameInfo, T, TInfo,
+ FromConstructor->isExplicit(),
+ D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
return ToFunction;
} else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {
ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg);
} else if (CXXConversionDecl *FromConversion =
dyn_cast<CXXConversionDecl>(D)) {
- Expr *ExplicitExpr = nullptr;
- if (FromConversion->getExplicitSpecifier().getExpr()) {
- auto Imp = importSeq(FromConversion->getExplicitSpecifier().getExpr());
- if (!Imp)
- return Imp.takeError();
- std::tie(ExplicitExpr) = *Imp;
- }
if (GetImportedOrCreateDecl<CXXConversionDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
- ExplicitSpecifier(ExplicitExpr,
- FromConversion->getExplicitSpecifier().getKind()),
- D->isConstexpr(), SourceLocation()))
+ FromConversion->isExplicit(), D->isConstexpr(), SourceLocation()))
return ToFunction;
} else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (GetImportedOrCreateDecl<CXXMethodDecl>(
if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
- if (!Constructor1->getExplicitSpecifier().isEquivalent(
- Constructor2->getExplicitSpecifier()))
+ if (Constructor1->isExplicit() != Constructor2->isExplicit())
return false;
}
if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
auto *Conversion2 = cast<CXXConversionDecl>(Method2);
- if (!Conversion1->getExplicitSpecifier().isEquivalent(
- Conversion2->getExplicitSpecifier()))
+ if (Conversion1->isExplicit() != Conversion2->isExplicit())
return false;
if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
Conversion2->getConversionType()))
FunctionDeclBits.SClass = S;
FunctionDeclBits.IsInline = isInlineSpecified;
FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
+ FunctionDeclBits.IsExplicitSpecified = false;
FunctionDeclBits.IsVirtualAsWritten = false;
FunctionDeclBits.IsPure = false;
FunctionDeclBits.HasInheritedPrototype = false;
void CXXDeductionGuideDecl::anchor() {}
-bool ExplicitSpecifier::isEquivalent(const ExplicitSpecifier Other) const {
- if ((getKind() != Other.getKind() ||
- getKind() == ExplicitSpecKind::Unresolved)) {
- if (getKind() == ExplicitSpecKind::Unresolved &&
- Other.getKind() == ExplicitSpecKind::Unresolved) {
- ODRHash SelfHash, OtherHash;
- SelfHash.AddStmt(getExpr());
- OtherHash.AddStmt(Other.getExpr());
- return SelfHash.CalculateHash() == OtherHash.CalculateHash();
- } else
- return false;
- }
- return true;
-}
-
-ExplicitSpecifier ExplicitSpecifier::getFromDecl(FunctionDecl *Function) {
- switch (Function->getDeclKind()) {
- case Decl::Kind::CXXConstructor:
- return cast<CXXConstructorDecl>(Function)->getExplicitSpecifier();
- case Decl::Kind::CXXConversion:
- return cast<CXXConversionDecl>(Function)->getExplicitSpecifier();
- case Decl::Kind::CXXDeductionGuide:
- return cast<CXXDeductionGuideDecl>(Function)->getExplicitSpecifier();
- default:
- return {};
- }
-}
-
CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
- ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
- TypeSourceInfo *TInfo, SourceLocation EndLocation) {
- return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T,
- TInfo, EndLocation);
+ ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit,
+ const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
+ SourceLocation EndLocation) {
+ return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, IsExplicit,
+ NameInfo, T, TInfo, EndLocation);
}
CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) CXXDeductionGuideDecl(
- C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
- QualType(), nullptr, SourceLocation());
+ return new (C, ID) CXXDeductionGuideDecl(C, nullptr, SourceLocation(), false,
+ DeclarationNameInfo(), QualType(),
+ nullptr, SourceLocation());
}
void CXXMethodDecl::anchor() {}
CXXConstructorDecl::CXXConstructorDecl(
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared,
+ bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared,
bool isConstexpr, InheritedConstructor Inherited)
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, SourceLocation()) {
setNumCtorInitializers(0);
setInheritingConstructor(static_cast<bool>(Inherited));
setImplicit(isImplicitlyDeclared);
- CXXConstructorDeclBits.HasTrailingExplicitSpecifier = ES.getExpr() ? 1 : 0;
if (Inherited)
*getTrailingObjects<InheritedConstructor>() = Inherited;
- setExplicitSpecifier(ES);
+ setExplicitSpecified(isExplicitSpecified);
}
void CXXConstructorDecl::anchor() {}
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
- uint64_t AllocKind) {
- bool hasTraillingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit);
- bool isInheritingConstructor =
- static_cast<bool>(AllocKind & TAKInheritsConstructor);
- unsigned Extra =
- additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
- isInheritingConstructor, hasTraillingExplicit);
+ bool Inherited) {
+ unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(Inherited);
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
- ExplicitSpecifier(), false, false, false, InheritedConstructor());
- Result->setInheritingConstructor(isInheritingConstructor);
- Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
- hasTraillingExplicit;
- Result->setExplicitSpecifier(ExplicitSpecifier());
+ false, false, false, false, InheritedConstructor());
+ Result->setInheritingConstructor(Inherited);
return Result;
}
-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) {
+CXXConstructorDecl *
+CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicit, bool isInline,
+ bool isImplicitlyDeclared, bool isConstexpr,
+ InheritedConstructor Inherited) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
unsigned Extra =
- additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
- Inherited ? 1 : 0, ES.getExpr() ? 1 : 0);
- return new (C, RD, Extra)
- CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline,
- isImplicitlyDeclared, isConstexpr, Inherited);
+ additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0);
+ return new (C, RD, Extra) CXXConstructorDecl(
+ C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline,
+ isImplicitlyDeclared, isConstexpr, Inherited);
}
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
CXXConversionDecl *
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXConversionDecl(
- C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
- false, ExplicitSpecifier(), false, SourceLocation());
+ return new (C, ID) CXXConversionDecl(C, nullptr, SourceLocation(),
+ DeclarationNameInfo(), QualType(),
+ nullptr, false, false, false,
+ SourceLocation());
}
-CXXConversionDecl *CXXConversionDecl::Create(
- ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- bool isInline, ExplicitSpecifier ES, bool isConstexpr,
- SourceLocation EndLocation) {
+CXXConversionDecl *
+CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicit,
+ bool isConstexpr, 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);
+ isInline, isExplicit, isConstexpr,
+ EndLocation);
}
bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
}
}
-static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
- PrintingPolicy &Policy,
- unsigned Indentation) {
- std::string Proto = "explicit";
- llvm::raw_string_ostream EOut(Proto);
- if (ES.getExpr()) {
- EOut << "(";
- ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation);
- EOut << ")";
- }
- EOut << " ";
- EOut.flush();
- Out << EOut.str();
-}
-
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!D->getDescribedFunctionTemplate() &&
!D->isFunctionTemplateSpecialization())
if (D->isVirtualAsWritten()) Out << "virtual ";
if (D->isModulePrivate()) Out << "__module_private__ ";
if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
- ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);
- if (ExplicitSpec.isSpecified())
- printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation);
+ if ((CDecl && CDecl->isExplicitSpecified()) ||
+ (ConversionDecl && ConversionDecl->isExplicitSpecified()) ||
+ (GuideDecl && GuideDecl->isExplicitSpecified()))
+ Out << "explicit ";
}
PrintingPolicy SubPolicy(Policy);
Builder.defineMacro("__cpp_template_template_args", "201611L");
// C++20 features.
- if (LangOpts.CPlusPlus2a)
- Builder.defineMacro("__cpp_conditional_explicit", "201806L");
if (LangOpts.Char8)
Builder.defineMacro("__cpp_char8_t", "201811L");
Builder.defineMacro("__cpp_impl_destroying_delete", "201806L");
Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
if (DS.isVirtualSpecified())
Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
- if (DS.hasExplicitSpecifier())
+ if (DS.isExplicitSpecified())
Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
DS.ClearFunctionSpecs();
}
- // Issue diagnostic and remove constexpr specifier if present.
+ // Issue diagnostic and remove constexpr specfier if present.
if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) {
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
DS.ClearConstexprSpec();
while (1) {
bool isInvalid = false;
bool isStorageClass = false;
- bool isAlreadyConsumed = false;
const char *PrevSpec = nullptr;
unsigned DiagID = 0;
- // This value need to be set when isAlreadyConsumed is set to true.
- SourceLocation RangeEnd;
-
// HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
// implementation for VS2013 uses _Atomic as an identifier for one of the
// classes in <atomic>.
isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
}
break;
- case tok::kw_explicit: {
- SourceLocation ExplicitLoc = Loc;
- SourceLocation CloseParenLoc;
- ExplicitSpecifier ExplicitSpec(nullptr, ExplicitSpecKind::ResolvedTrue);
- isAlreadyConsumed = true;
- RangeEnd = ExplicitLoc;
- ConsumeToken(); // kw_explicit
- if (Tok.is(tok::l_paren)) {
- if (getLangOpts().CPlusPlus2a) {
- ExprResult ExplicitExpr(static_cast<Expr *>(nullptr));
- BalancedDelimiterTracker Tracker(*this, tok::l_paren);
- Tracker.consumeOpen();
- ExplicitExpr = ParseConstantExpression();
- RangeEnd = Tok.getLocation();
- if (ExplicitExpr.isUsable()) {
- CloseParenLoc = Tok.getLocation();
- Tracker.consumeClose();
- ExplicitSpec =
- Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get());
- } else
- Tracker.skipToEnd();
- } else
- Diag(Tok.getLocation(), diag::warn_cxx2a_compat_explicit_bool);
- }
- isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID,
- ExplicitSpec, CloseParenLoc);
+ case tok::kw_explicit:
+ isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID);
break;
- }
case tok::kw__Noreturn:
if (!getLangOpts().C11)
Diag(Loc, diag::ext_c11_noreturn);
// If a type specifier follows, it will be diagnosed elsewhere.
continue;
}
-
- assert((!isAlreadyConsumed || RangeEnd != SourceLocation()) &&
- "both or neither of isAlreadyConsumed and "
- "RangeEnd needs to be set");
- DS.SetRangeEnd(isAlreadyConsumed ? RangeEnd : Tok.getLocation());
-
// If the specifier wasn't legal, issue a diagnostic.
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
assert(DiagID);
if (DiagID == diag::ext_duplicate_declspec ||
- DiagID == diag::ext_warn_duplicate_declspec ||
- DiagID == diag::err_duplicate_declspec)
- Diag(Loc, DiagID) << PrevSpec
- << FixItHint::CreateRemoval(
- SourceRange(Loc, DS.getEndLoc()));
+ DiagID == diag::ext_warn_duplicate_declspec)
+ Diag(Tok, DiagID)
+ << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());
else if (DiagID == diag::err_opencl_unknown_type_specifier) {
- Diag(Loc, DiagID) << getLangOpts().OpenCLCPlusPlus
- << getLangOpts().getOpenCLVersionTuple().getAsString()
- << PrevSpec << isStorageClass;
+ Diag(Tok, DiagID) << getLangOpts().OpenCLCPlusPlus
+ << getLangOpts().getOpenCLVersionTuple().getAsString()
+ << PrevSpec << isStorageClass;
} else
- Diag(Loc, DiagID) << PrevSpec;
+ Diag(Tok, DiagID) << PrevSpec;
}
- if (DiagID != diag::err_bool_redeclaration && !isAlreadyConsumed)
+ DS.SetRangeEnd(Tok.getLocation());
+ if (DiagID != diag::err_bool_redeclaration)
// After an error the next token can be an annotation token.
ConsumeAnyToken();
if (hasTypeSpecifier())
Res |= PQ_TypeSpecifier;
- if (FS_inline_specified || FS_virtual_specified || hasExplicitSpecifier() ||
+ if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified ||
FS_noreturn_specified || FS_forceinline_specified)
Res |= PQ_FunctionSpecifier;
return Res;
}
bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID,
- ExplicitSpecifier ExplicitSpec,
- SourceLocation CloseParenLoc) {
- assert((ExplicitSpec.getKind() == ExplicitSpecKind::ResolvedTrue ||
- ExplicitSpec.getExpr()) &&
- "invalid ExplicitSpecifier");
+ const char *&PrevSpec,
+ unsigned &DiagID) {
// 'explicit explicit' is ok, but warn as this is likely not what the user
// intended.
- if (hasExplicitSpecifier()) {
- DiagID = (ExplicitSpec.getExpr() || FS_explicit_specifier.getExpr())
- ? diag::err_duplicate_declspec
- : diag::ext_warn_duplicate_declspec;
+ if (FS_explicit_specified) {
+ DiagID = diag::warn_duplicate_declspec;
PrevSpec = "explicit";
return true;
}
- FS_explicit_specifier = ExplicitSpec;
+ FS_explicit_specified = true;
FS_explicitLoc = Loc;
- FS_explicitCloseParenLoc = CloseParenLoc;
return false;
}
// The explicit specifier shall be used only in the declaration of
// a constructor or conversion function within its class
// definition;
- if (isFriendSpecified() && (isVirtualSpecified() || hasExplicitSpecifier())) {
+ if (isFriendSpecified() && (isVirtualSpecified() || isExplicitSpecified())) {
StringRef Keyword;
- FixItHint Hint;
SourceLocation SCLoc;
if (isVirtualSpecified()) {
Keyword = "virtual";
SCLoc = getVirtualSpecLoc();
- Hint = FixItHint::CreateRemoval(SCLoc);
} else {
Keyword = "explicit";
SCLoc = getExplicitSpecLoc();
- Hint = FixItHint::CreateRemoval(getExplicitSpecRange());
}
+ FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
S.Diag(SCLoc, diag::err_friend_decl_spec)
<< Keyword << Hint;
- FS_virtual_specified = false;
- FS_explicit_specifier = ExplicitSpecifier();
+ FS_virtual_specified = FS_explicit_specified = false;
FS_virtualLoc = FS_explicitLoc = SourceLocation();
}
AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
CandidateSet,
/*SuppressUsedConversions=*/false,
- /*PartialOverloading=*/true,
- /*AllowExplicit*/ true);
+ /*PartialOverloading=*/true);
} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, C->getAccess()),
/*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
/*SuppressUsedConversions=*/false,
- /*PartialOverloading=*/true,
- /*AllowExplicit*/ true);
+ /*PartialOverloading=*/true);
}
}
Diag(DS.getVirtualSpecLoc(),
diag::err_virtual_non_function);
- if (DS.hasExplicitSpecifier())
+ if (DS.isExplicitSpecified())
Diag(DS.getExplicitSpecLoc(),
diag::err_explicit_non_function);
return NewFD;
}
- ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
+ bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
// Check that the return type is not an abstract class type.
R = SemaRef.CheckConstructorDeclarator(D, R, SC);
return CXXConstructorDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
- TInfo, ExplicitSpecifier, isInline,
+ TInfo, isExplicit, isInline,
/*isImplicitlyDeclared=*/false, isConstexpr);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
IsVirtualOkay = true;
return CXXConversionDecl::Create(
SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
- TInfo, isInline, ExplicitSpecifier, isConstexpr, SourceLocation());
+ TInfo, isInline, isExplicit, isConstexpr, SourceLocation());
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
SemaRef.CheckDeductionGuideDeclarator(D, R, SC);
return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
- ExplicitSpecifier, NameInfo, R, TInfo,
+ isExplicit, NameInfo, R, TInfo,
D.getEndLoc());
} else if (DC->isRecord()) {
// If the name of the function is the same as the name of the record,
if (getLangOpts().CPlusPlus) {
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
- bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();
+ bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
isFriend = D.getDeclSpec().isFriendSpecified();
if (isFriend && !isInline && D.isFunctionDefinition()) {
// The explicit specifier shall be used only in the declaration of a
// constructor or conversion function within its class definition;
// see 12.3.1 and 12.3.2.
- if (hasExplicit && !NewFD->isInvalidDecl() &&
+ if (isExplicit && !NewFD->isInvalidDecl() &&
!isa<CXXDeductionGuideDecl>(NewFD)) {
if (!CurContext->isRecord()) {
// 'explicit' was specified outside of the class.
Diag(D.getDeclSpec().getExplicitSpecLoc(),
diag::err_explicit_out_of_class)
- << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecRange());
+ << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
} else if (!isa<CXXConstructorDecl>(NewFD) &&
!isa<CXXConversionDecl>(NewFD)) {
// 'explicit' was specified on a function that wasn't a constructor
// or conversion function.
Diag(D.getDeclSpec().getExplicitSpecLoc(),
diag::err_explicit_non_ctor_or_conv_function)
- << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecRange());
+ << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
}
}
Invalid = true;
}
- // C++17 [temp.deduct.guide]p3:
- // Two deduction guide declarations in the same translation unit
- // for the same class template shall not have equivalent
- // parameter-declaration-clauses.
- if (isa<CXXDeductionGuideDecl>(New) &&
- !New->isFunctionTemplateSpecialization()) {
- Diag(New->getLocation(), diag::err_deduction_guide_redeclared);
+ // FIXME: It's not clear what should happen if multiple declarations of a
+ // deduction guide have different explicitness. For now at least we simply
+ // reject any case where the explicitness changes.
+ auto *NewGuide = dyn_cast<CXXDeductionGuideDecl>(New);
+ if (NewGuide && NewGuide->isExplicitSpecified() !=
+ cast<CXXDeductionGuideDecl>(Old)->isExplicitSpecified()) {
+ Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch)
+ << NewGuide->isExplicitSpecified();
Diag(Old->getLocation(), diag::note_previous_declaration);
}
R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo());
// C++0x explicit conversion operators.
- if (DS.hasExplicitSpecifier() && !getLangOpts().CPlusPlus2a)
+ if (DS.isExplicitSpecified())
Diag(DS.getExplicitSpecLoc(),
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_explicit_conversion_functions
: diag::ext_explicit_conversion_functions)
- << SourceRange(DS.getExplicitSpecRange());
+ << SourceRange(DS.getExplicitSpecLoc());
}
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
};
}
-bool Sema::tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec) {
- llvm::APSInt Result;
- ExprResult Converted = CheckConvertedConstantExpression(
- ExplicitSpec.getExpr(), Context.BoolTy, Result, CCEK_ExplicitBool);
- ExplicitSpec.setExpr(Converted.get());
- if (Converted.isUsable() && !Converted.get()->isValueDependent()) {
- ExplicitSpec.setKind(Result.getBoolValue()
- ? ExplicitSpecKind::ResolvedTrue
- : ExplicitSpecKind::ResolvedFalse);
- return true;
- }
- ExplicitSpec.setKind(ExplicitSpecKind::Unresolved);
- return false;
-}
-
-ExplicitSpecifier Sema::ActOnExplicitBoolSpecifier(Expr *ExplicitExpr) {
- ExplicitSpecifier ES(ExplicitExpr, ExplicitSpecKind::Unresolved);
- if (!ExplicitExpr->isTypeDependent())
- tryResolveExplicitSpecifier(ES);
- return ES;
-}
-
static Sema::ImplicitExceptionSpecification
ComputeDefaultedSpecialMemberExceptionSpec(
Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
= Context.DeclarationNames.getCXXConstructorName(ClassType);
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
- Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(),
- /*TInfo=*/nullptr, ExplicitSpecifier(),
- /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr);
+ Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(),
+ /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true, Constexpr);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create(
Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
- BaseCtor->getExplicitSpecifier(), /*Inline=*/true,
+ BaseCtor->isExplicit(), /*Inline=*/true,
/*ImplicitlyDeclared=*/true, Constexpr,
InheritedConstructor(Shadow, BaseCtor));
if (Shadow->isInvalidDecl())
// member of its class.
CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
- ExplicitSpecifier(),
- /*isInline=*/true,
- /*isImplicitlyDeclared=*/true, Constexpr);
+ /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+ Constexpr);
CopyConstructor->setAccess(AS_public);
CopyConstructor->setDefaulted();
// member of its class.
CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
- ExplicitSpecifier(),
- /*isInline=*/true,
- /*isImplicitlyDeclared=*/true, Constexpr);
+ /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+ Constexpr);
MoveConstructor->setAccess(AS_public);
MoveConstructor->setDefaulted();
hasCopyOrMoveCtorParam(S.Context, Info));
if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(
- Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions,
- /*PartialOverloading=*/false, AllowExplicit);
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, Args,
+ CandidateSet, SuppressUserConversions);
else {
// C++ [over.match.copy]p1:
// - When initializing a temporary to be bound to the first parameter
hasCopyOrMoveCtorParam(S.Context, Info);
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
CandidateSet, SuppressUserConversions,
- /*PartialOverloading=*/false, AllowExplicit,
- AllowExplicitConv);
+ /*PartialOverloading=*/false,
+ /*AllowExplicit=*/AllowExplicitConv);
}
}
else
Conv = cast<CXXConversionDecl>(D);
- if (AllowExplicit || !Conv->isExplicit()) {
+ if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(
- ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
- CandidateSet, AllowExplicit, AllowExplicit,
- /*AllowResultConversion*/ false);
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+ ActingDC, Initializer, DestType,
+ CandidateSet, AllowExplicit,
+ /*AllowResultConversion*/false);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
DestType, CandidateSet, AllowExplicit,
- AllowExplicit,
- /*AllowResultConversion*/ false);
+ /*AllowResultConversion*/false);
}
}
}
if (!Info.Constructor->isInvalidDecl() &&
Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) {
if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(
- Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr, Initializer, CandidateSet,
- /*SuppressUserConversions=*/true,
- /*PartialOverloading*/ false, AllowExplicitCtors);
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr,
+ Initializer, CandidateSet,
+ /*SuppressUserConversions=*/true);
else
- S.AddOverloadCandidate(
- Info.Constructor, Info.FoundDecl, Initializer, CandidateSet,
- /*SuppressUserConversions=*/true,
- /*PartialOverloading*/ false, AllowExplicitCtors);
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
+ Initializer, CandidateSet,
+ /*SuppressUserConversions=*/true);
}
}
}
// candidates with reference-compatible results? That might be needed to
// break recursion.
if ((AllowExplicitConvs || !Conv->isExplicit()) &&
- (AllowRValues ||
- Conv->getConversionType()->isLValueReferenceType())) {
+ (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
if (ConvTemplate)
- S.AddTemplateConversionCandidate(
- ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
- CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs);
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+ ActingDC, Initializer,
+ DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/
+ false);
else
- S.AddConversionCandidate(
- Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs);
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
+ Initializer, DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
}
}
}
if (!Info.Constructor->isInvalidDecl() &&
Info.Constructor->isConvertingConstructor(AllowExplicit)) {
if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(
- Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr, Initializer, CandidateSet,
- /*SuppressUserConversions=*/true,
- /*PartialOverloading*/ false, AllowExplicit);
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr,
+ Initializer, CandidateSet,
+ /*SuppressUserConversions=*/true);
else
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
Initializer, CandidateSet,
- /*SuppressUserConversions=*/true,
- /*PartialOverloading*/ false, AllowExplicit);
+ /*SuppressUserConversions=*/true);
}
}
}
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(
- ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
- CandidateSet, AllowExplicit, AllowExplicit);
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+ ActingDC, Initializer, DestType,
+ CandidateSet, AllowExplicit);
else
- S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
- DestType, CandidateSet, AllowExplicit,
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
+ Initializer, DestType, CandidateSet,
AllowExplicit);
}
}
OverloadCandidateSet::iterator Best;
bool HasAnyDeductionGuide = false;
- bool AllowExplicit = !Kind.isCopyInit() || ListInit;
auto tryToResolveOverload =
[&](bool OnlyListConstructors) -> OverloadingResult {
// converting constructors (12.3.1) of that class.
// C++ [over.match.copy]p1: (non-list copy-initialization from class)
// The converting constructors of T are candidate functions.
- if (!AllowExplicit) {
+ if (Kind.isCopyInit() && !ListInit) {
// Only consider converting constructors.
if (GD->isExplicit())
continue;
if (TD)
AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr,
- Inits, Candidates, SuppressUserConversions,
- /*PartialOverloading*/ false,
- AllowExplicit);
+ Inits, Candidates,
+ SuppressUserConversions);
else
AddOverloadCandidate(GD, I.getPair(), Inits, Candidates,
SuppressUserConversions);
CXXConversionDecl *Conversion = CXXConversionDecl::Create(
S.Context, Class, Loc,
DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI,
- /*isInline=*/true, ExplicitSpecifier(),
+ /*isInline=*/true, /*isExplicit=*/false,
/*isConstexpr=*/S.getLangOpts().CPlusPlus17,
CallOperator->getBody()->getEndLoc());
Conversion->setAccess(AS_public);
CXXConversionDecl *Conversion = CXXConversionDecl::Create(
S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy,
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
- /*isInline=*/true, ExplicitSpecifier(),
+ /*isInline=*/true, /*isExplicit=*/false,
/*isConstexpr=*/false, CallOperator->getBody()->getEndLoc());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
else if (CtorInfo)
AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,
- llvm::makeArrayRef(&Arg, NumArgs), OCS,
- /*SuppressUserConversions*/ true,
- /*PartialOverloading*/ false,
- /*AllowExplcit*/ true);
+ llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
else
AddOverloadCandidate(M, Cand, llvm::makeArrayRef(&Arg, NumArgs), OCS,
- /*SuppressUserConversions*/ true,
- /*PartialOverloading*/ false,
- /*AllowExplcit*/ true);
+ true);
} else if (FunctionTemplateDecl *Tmpl =
dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) {
if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, From,
- CandidateSet, SuppressUserConversions,
- /*PartialOverloading*/ false,
- AllowExplicit);
+ CandidateSet, SuppressUserConversions);
else
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From,
- CandidateSet, SuppressUserConversions,
- /*PartialOverloading*/ false, AllowExplicit);
+ CandidateSet, SuppressUserConversions);
}
}
S.AddTemplateOverloadCandidate(
Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs),
- CandidateSet, SuppressUserConversions,
- /*PartialOverloading*/ false, AllowExplicit);
+ CandidateSet, SuppressUserConversions);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
llvm::makeArrayRef(Args, NumArgs),
- CandidateSet, SuppressUserConversions,
- /*PartialOverloading*/ false, AllowExplicit);
+ CandidateSet, SuppressUserConversions);
}
}
}
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(
- ConvTemplate, FoundDecl, ActingContext, From, ToType,
- CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit);
+ S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
+ ActingContext, From, ToType,
+ CandidateSet,
+ AllowObjCConversionOnExplicit);
else
- S.AddConversionCandidate(
- Conv, FoundDecl, ActingContext, From, ToType, CandidateSet,
- AllowObjCConversionOnExplicit, AllowExplicit);
+ S.AddConversionCandidate(Conv, FoundDecl, ActingContext,
+ From, ToType, CandidateSet,
+ AllowObjCConversionOnExplicit);
}
}
}
}
if (ConvTemplate)
- S.AddTemplateConversionCandidate(
- ConvTemplate, I.getPair(), ActingDC, Init, DeclType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false, AllowExplicit);
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
+ Init, DeclType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
else
- S.AddConversionCandidate(
- Conv, I.getPair(), ActingDC, Init, DeclType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false, AllowExplicit);
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
+ DeclType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
// condition shall be a contextually converted constant expression of type
// bool.
ImplicitConversionSequence ICS =
- CCE == Sema::CCEK_ConstexprIf || CCE == Sema::CCEK_ExplicitBool
+ CCE == Sema::CCEK_ConstexprIf
? TryContextuallyConvertToBool(S, From)
: TryCopyInitialization(S, From, T,
/*SuppressUserConversions=*/false,
if (ConvTemplate)
SemaRef.AddTemplateConversionCandidate(
- ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false, /*AllowExplicit*/ true);
+ ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
else
SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From,
ToType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false,
- /*AllowExplicit*/ true);
+ /*AllowObjCConversionOnExplicit=*/false);
}
}
/// \param PartialOverloading true if we are performing "partial" overloading
/// based on an incomplete set of function arguments. This feature is used by
/// code completion.
-void Sema::AddOverloadCandidate(
- FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
- bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
- ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions) {
+void Sema::AddOverloadCandidate(FunctionDecl *Function,
+ DeclAccessPair FoundDecl, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ bool SuppressUserConversions,
+ bool PartialOverloading, bool AllowExplicit,
+ ADLCallKind IsADLCandidate,
+ ConversionSequenceList EarlyConversions) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
QualType ParamType = Proto->getParamType(ArgIdx);
- Candidate.Conversions[ArgIdx] = TryCopyInitialization(
- *this, Args[ArgIdx], ParamType, SuppressUserConversions,
- /*InOverloadResolution=*/true,
- /*AllowObjCWritebackConversion=*/
- getLangOpts().ObjCAutoRefCount, AllowExplicitConversions);
+ Candidate.Conversions[ArgIdx]
+ = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+ SuppressUserConversions,
+ /*InOverloadResolution=*/true,
+ /*AllowObjCWritebackConversion=*/
+ getLangOpts().ObjCAutoRefCount,
+ AllowExplicit);
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
}
}
- if (!AllowExplicit) {
- ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Function);
- if (ES.getKind() != ExplicitSpecKind::ResolvedFalse) {
- Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_explicit_resolved;
- return;
- }
- }
-
if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
- bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate) {
+ bool PartialOverloading, ADLCallKind IsADLCandidate) {
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
// Add the function template specialization produced by template argument
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- AddOverloadCandidate(
- Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
- PartialOverloading, AllowExplicit,
- /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions);
+ AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
+ SuppressUserConversions, PartialOverloading,
+ /*AllowExplicit*/ false, IsADLCandidate, Conversions);
}
/// Check that implicit conversion sequences can be formed for each argument
/// and ToType is the type that we're eventually trying to convert to
/// (which may or may not be the same type as the type that the
/// conversion function produces).
-void Sema::AddConversionCandidate(
- CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
- bool AllowExplicit, bool AllowResultConversion) {
+void
+Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
"Can only end up with a standard conversion sequence or failure");
}
- if (!AllowExplicit && Conversion->getExplicitSpecifier().getKind() !=
- ExplicitSpecKind::ResolvedFalse) {
- Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_explicit_resolved;
- return;
- }
-
if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
/// to deduce the template arguments of the conversion function
/// template from the type that we are converting to (C++
/// [temp.deduct.conv]).
-void Sema::AddTemplateConversionCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingDC, Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
- bool AllowExplicit, bool AllowResultConversion) {
+void
+Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingDC,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet,
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion) {
assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
"Only conversion function templates permitted here");
assert(Specialization && "Missing function template specialization?");
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
CandidateSet, AllowObjCConversionOnExplicit,
- AllowExplicit, AllowResultConversion);
+ AllowResultConversion);
}
/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet,
/*SupressUserConversions=*/false, PartialOverloading,
- /*AllowExplicitConversions*/ false,
- /*AllowExplicit*/ false, ADLCallKind::UsesADL);
+ /*AllowExplicit=*/false, ADLCallKind::UsesADL);
} else {
- AddTemplateOverloadCandidate(
- cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, Args,
- CandidateSet,
- /*SupressUserConversions=*/false, PartialOverloading,
- /*AllowExplicit*/ false, ADLCallKind::UsesADL);
+ AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl,
+ ExplicitTemplateArgs, Args, CandidateSet,
+ /*SupressUserConversions=*/false,
+ PartialOverloading, ADLCallKind::UsesADL);
}
}
}
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
}
-static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) {
- ExplicitSpecifier ES;
- const char *DeclName;
- switch (Cand->Function->getDeclKind()) {
- case Decl::Kind::CXXConstructor:
- ES = cast<CXXConstructorDecl>(Cand->Function)->getExplicitSpecifier();
- DeclName = "constructor";
- break;
- case Decl::Kind::CXXConversion:
- ES = cast<CXXConversionDecl>(Cand->Function)->getExplicitSpecifier();
- DeclName = "conversion operator";
- break;
- case Decl::Kind::CXXDeductionGuide:
- ES = cast<CXXDeductionGuideDecl>(Cand->Function)->getExplicitSpecifier();
- DeclName = "deductiong guide";
- break;
- default:
- llvm_unreachable("invalid Decl");
- }
- assert(ES.getExpr() && "null expression should be handled before");
- S.Diag(Cand->Function->getLocation(),
- diag::note_ovl_candidate_explicit_forbidden)
- << DeclName;
- S.Diag(ES.getExpr()->getBeginLoc(),
- diag::note_explicit_bool_resolved_to_true);
-}
-
static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Callee = Cand->Function;
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
- case ovl_fail_explicit_resolved:
- return DiagnoseFailedExplicitSpec(S, Cand);
-
case ovl_fail_ext_disabled:
return DiagnoseOpenCLExtensionDisabled(S, Cand);
// Microsoft supports direct constructor calls.
if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) {
- AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args,
- CandidateSet,
- /*SuppressUserConversions*/ false,
- /*PartialOverloading*/ false,
- /*AllowExplicit*/ true);
+ AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(),
+ Args, CandidateSet);
} else if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
// If explicit template arguments were provided, we can't call a
// non-template member function.
if (DS.isVirtualSpecified())
EmitDiag(DS.getVirtualSpecLoc());
- if (DS.hasExplicitSpecifier())
+ if (DS.isExplicitSpecified())
EmitDiag(DS.getExplicitSpecLoc());
if (DS.isNoreturnSpecified())
return nullptr;
TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
- return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(),
- NewTInfo, CD->getBeginLoc(), CD->getLocation(),
+ return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo,
+ CD->getBeginLoc(), CD->getLocation(),
CD->getEndLoc());
}
Params.push_back(NewParam);
}
- return buildDeductionGuide(Template->getTemplateParameters(),
- ExplicitSpecifier(), TSI, Loc, Loc, Loc);
+ return buildDeductionGuide(Template->getTemplateParameters(), false, TSI,
+ Loc, Loc, Loc);
}
private:
}
NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams,
- ExplicitSpecifier ES, TypeSourceInfo *TInfo,
+ bool Explicit, TypeSourceInfo *TInfo,
SourceLocation LocStart, SourceLocation Loc,
SourceLocation LocEnd) {
DeclarationNameInfo Name(DeductionGuideName, Loc);
// Build the implicit deduction guide template.
auto *Guide =
- CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
- TInfo->getType(), TInfo, LocEnd);
+ CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, Explicit,
+ Name, TInfo->getType(), TInfo, LocEnd);
Guide->setImplicit();
Guide->setParams(Params);
Attr.getSpellingListIndex());
}
-static ExplicitSpecifier
-instantiateExplicitSpecifier(Sema &S,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- ExplicitSpecifier ES, FunctionDecl *New) {
- if (!ES.getExpr())
- return ES;
- Expr *OldCond = ES.getExpr();
- Expr *Cond = nullptr;
- {
- EnterExpressionEvaluationContext Unevaluated(
- S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- ExprResult SubstResult = S.SubstExpr(OldCond, TemplateArgs);
- if (SubstResult.isInvalid()) {
- return ExplicitSpecifier::Invalid();
- }
- Cond = SubstResult.get();
- }
- ExplicitSpecifier Result(Cond, ES.getKind());
- if (!Cond->isTypeDependent())
- S.tryResolveExplicitSpecifier(Result);
- return Result;
-}
-
static void instantiateDependentAMDGPUWavesPerEUAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const AMDGPUWavesPerEUAttr &Attr, Decl *New) {
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
- ExplicitSpecifier InstantiatedExplicitSpecifier;
- if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) {
- InstantiatedExplicitSpecifier = instantiateExplicitSpecifier(
- SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide);
- if (InstantiatedExplicitSpecifier.isInvalid())
- return nullptr;
- }
-
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
FunctionDecl *Function;
if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) {
Function = CXXDeductionGuideDecl::Create(
- SemaRef.Context, DC, D->getInnerLocStart(),
- InstantiatedExplicitSpecifier, NameInfo, T, TInfo,
- D->getSourceRange().getEnd());
+ SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
+ NameInfo, T, TInfo, D->getSourceRange().getEnd());
if (DGuide->isCopyDeductionCandidate())
cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
Function->setAccess(D->getAccess());
}
}
- ExplicitSpecifier InstantiatedExplicitSpecifier =
- instantiateExplicitSpecifier(SemaRef, TemplateArgs,
- ExplicitSpecifier::getFromDecl(D), D);
- if (InstantiatedExplicitSpecifier.isInvalid())
- return nullptr;
-
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
DeclarationNameInfo NameInfo
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
- Method = CXXConstructorDecl::Create(
- SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
- InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false,
- Constructor->isConstexpr());
+ Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
+ StartLoc, NameInfo, T, TInfo,
+ Constructor->isExplicit(),
+ Constructor->isInlineSpecified(),
+ false, Constructor->isConstexpr());
Method->setRangeEnd(Constructor->getEndLoc());
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
Method = CXXConversionDecl::Create(
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
- Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier,
+ Conversion->isInlineSpecified(), Conversion->isExplicit(),
Conversion->isConstexpr(), Conversion->getEndLoc());
} else {
StorageClass SC = D->isStatic() ? SC_Static : SC_None;
FD->setStorageClass(static_cast<StorageClass>(Record.readInt()));
FD->setInlineSpecified(Record.readInt());
FD->setImplicitlyInline(Record.readInt());
+ FD->setExplicitSpecified(Record.readInt());
FD->setVirtualAsWritten(Record.readInt());
FD->setPure(Record.readInt());
FD->setHasInheritedPrototype(Record.readInt());
}
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
- D->setExplicitSpecifier(Record.readExplicitSpec());
VisitFunctionDecl(D);
D->setIsCopyDeductionCandidate(Record.readInt());
}
void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
// We need the inherited constructor information to merge the declaration,
// so we have to read it before we call VisitCXXMethodDecl.
- D->setExplicitSpecifier(Record.readExplicitSpec());
if (D->isInheritingConstructor()) {
auto *Shadow = ReadDeclAs<ConstructorUsingShadowDecl>();
auto *Ctor = ReadDeclAs<CXXConstructorDecl>();
}
void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
- D->setExplicitSpecifier(Record.readExplicitSpec());
VisitCXXMethodDecl(D);
}
D = CXXMethodDecl::CreateDeserialized(Context, ID);
break;
case DECL_CXX_CONSTRUCTOR:
- D = CXXConstructorDecl::CreateDeserialized(Context, ID, Record.readInt());
+ D = CXXConstructorDecl::CreateDeserialized(Context, ID, false);
+ break;
+ case DECL_CXX_INHERITED_CONSTRUCTOR:
+ D = CXXConstructorDecl::CreateDeserialized(Context, ID, true);
break;
case DECL_CXX_DESTRUCTOR:
D = CXXDestructorDecl::CreateDeserialized(Context, ID);
RECORD(DECL_CXX_RECORD);
RECORD(DECL_CXX_METHOD);
RECORD(DECL_CXX_CONSTRUCTOR);
+ RECORD(DECL_CXX_INHERITED_CONSTRUCTOR);
RECORD(DECL_CXX_DESTRUCTOR);
RECORD(DECL_CXX_CONVERSION);
RECORD(DECL_ACCESS_SPEC);
Record.push_back(static_cast<int>(D->getStorageClass())); // FIXME: stable encoding
Record.push_back(D->isInlineSpecified());
Record.push_back(D->isInlined());
+ Record.push_back(D->isExplicitSpecified());
Record.push_back(D->isVirtualAsWritten());
Record.push_back(D->isPure());
Record.push_back(D->hasInheritedPrototype());
Code = serialization::DECL_FUNCTION;
}
-static void addExplicitSpecifier(ExplicitSpecifier ES,
- ASTRecordWriter &Record) {
- uint64_t Kind = static_cast<uint64_t>(ES.getKind());
- Kind = Kind << 1 | static_cast<bool>(ES.getExpr());
- Record.push_back(Kind);
- if (ES.getExpr()) {
- Record.AddStmt(ES.getExpr());
- }
-}
-
void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
- addExplicitSpecifier(D->getExplicitSpecifier(), Record);
VisitFunctionDecl(D);
Record.push_back(D->isCopyDeductionCandidate());
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
}
void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
- Record.push_back(D->getTraillingAllocKind());
- addExplicitSpecifier(D->getExplicitSpecifier(), Record);
if (auto Inherited = D->getInheritedConstructor()) {
Record.AddDeclRef(Inherited.getShadowDecl());
Record.AddDeclRef(Inherited.getConstructor());
+ Code = serialization::DECL_CXX_INHERITED_CONSTRUCTOR;
+ } else {
+ Code = serialization::DECL_CXX_CONSTRUCTOR;
}
VisitCXXMethodDecl(D);
- Code = serialization::DECL_CXX_CONSTRUCTOR;
+
+ Code = D->isInheritingConstructor()
+ ? serialization::DECL_CXX_INHERITED_CONSTRUCTOR
+ : serialization::DECL_CXX_CONSTRUCTOR;
}
void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
}
void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
- addExplicitSpecifier(D->getExplicitSpecifier(), Record);
VisitCXXMethodDecl(D);
Code = serialization::DECL_CXX_CONVERSION;
}
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitSpecified
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure
Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto
#endif
mutable A(int(&)[27]) -> A<int>; // expected-error-re {{{{'mutable' cannot be applied to|illegal storage class on}} function}}
virtual A(int(&)[28]) -> A<int>; // expected-error {{'virtual' can only appear on non-static member functions}}
-const A(int(&)[31]) -> A<int>; // expected-error {{deduction guide cannot be declared 'const'}}
+const A(int(&)[28]) -> A<int>; // expected-error {{deduction guide cannot be declared 'const'}}
const volatile static constexpr inline A(int(&)[29]) -> A<int>; // expected-error {{deduction guide cannot be declared 'static inline constexpr const volatile'}}
// The same restrictions apply to the parameter-declaration-clause of a
// deduction guide as in a function declaration.
template<typename T> struct A {};
-A(void) -> A<int>; // expected-note {{previous}}
+A(void) -> A<int>; // ok
A(void, int) -> A<int>; // expected-error {{'void' must be the first and only parameter if specified}}
-A() -> A<int>; // expected-error {{redeclaration of deduction guide}}
-// expected-note@-1 {{previous}}
+// We interpret this as also extending to the validity of redeclarations. It's
+// a bit of a stretch (OK, a lot of a stretch) but it gives desirable answers.
+A() -> A<int>; // ok, redeclaration
A() -> A<int>; // expected-note {{previous}}
-// expected-error@-1 {{redeclaration of deduction guide}}
A() -> A<float>; // FIXME: "functions" is a poor term. expected-error {{functions that differ only in their return type cannot be overloaded}}
template<typename T> A(T) -> A<typename T::foo>;
+++ /dev/null
-// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t-cxx2a
-// RUN: %clang_cc1 -std=c++2a -DUSE_PCH -include-pch %t-cxx2a %s -ast-print -verify | FileCheck %s
-
-#ifndef USE_PCH
-namespace inheriting_constructor {
- struct S {};
-
- template<typename X, typename Y> struct T {
- template<typename A>
- explicit((Y{}, true)) T(A &&a) {}
- };
-
- template<typename X, typename Y> struct U : T<X, Y> {
- using T<X, Y>::T;
- };
-
- U<S, char> foo(char ch) {
- return U<S, char>(ch);
- }
-}
-#else
-namespace inheriting_constructor {
-U<S, char> a = foo('0');
-}
-
-//CHECK: explicit((char{} , true))
-
-#endif
-
-namespace basic {
-#ifndef USE_PCH
-
-struct B {};
-
-struct A {
- explicit A(int);
- explicit(false) operator bool();
- explicit(true) operator B();
-};
-#else
-//expected-note@-6+ {{candidate constructor}}
-//expected-note@-9+ {{candidate constructor}}
-//expected-note@-6+ {{candidate function}}
-
-//CHECK: explicit{{ +}}A(
-//CHECK-NEXT: explicit(false){{ +}}operator
-//CHECK-NEXT: explicit(true){{ +}}operator
-A a = 0; //expected-error {{no viable conversion}}
-A a1(0);
-
-bool b = a1;
-B b1 = a1; //expected-error {{no viable conversion}}
-
-#endif
-}
-
-
-namespace templ {
-#ifndef USE_PCH
-
-template<bool b>
-struct B {
- static constexpr bool value = b;
-};
-
-template<bool b>
-struct A {
- explicit(b) A(B<b>) {}
- template<typename T>
- explicit(b ^ T::value) operator T();
-};
-B<true> b_true;
-B<false> b_false;
-#else
-//expected-note@-8 {{candidate template ignored}}
-//expected-note@-8+ {{explicit constructor}}
-//expected-note@-15+ {{candidate constructor}}
-//expected-note@-8+ {{candidate conversion operator ignored}}
-//expected-note@-9+ {{explicit(bool) specifier resolved to true}}
-//expected-note@-12 {{explicit(bool) specifier resolved to true}}
-//expected-note@-13+ {{candidate deductiong guide ignored}}
-
-//CHECK: explicit(b){{ +}}A
-//CHECK: explicit(b{{ +}}^{{ +}}T::value){{ +}}operator
-
-A a = { b_true }; //expected-error {{class template argument deduction}}
-A a0 = b_true; //expected-error {{no viable constructor or deduction guide}}
-A a_true(b_true);
-A a_false = b_false;
-
-B<true> b = a_true;
-B<true> b1 = a_false; //expected-error {{no viable conversion}}
-B<false> b2(a_true);
-
-#endif
-
-}
-
-namespace guide {
-
-#ifndef USE_PCH
-
-template<typename T>
-struct A {
- A(T);
-};
-
-template<typename T>
-explicit(true) A(T) -> A<T>;
-
-explicit(false) A(int) -> A<int>;
-
-#else
-//expected-note@-5 {{explicit deduction guide}}
-
-//CHECK: explicit(true){{ +}}A(
-//CHECK: explicit(false){{ +}}A(
-
-A a = { 0.0 }; //expected-error {{explicit deduction guide}}
-A a1 = { 0 };
-
-#endif
-
-}
#if defined(__cpp_conditional_explicit)
struct TestConditionalExplicit {
- explicit(!__builtin_is_constant_evaluated()) TestConditionalExplicit(int) {}
+ explicit(__builtin_is_constant_evaluated()) TestConditionalExplicit(int) {}
};
TestConditionalExplicit e = 42;
#endif
// expected-error@-8 {{cannot initialize a variable of type 'const char *' with an lvalue of type 'const char8_t [6]'}}
// expected-error@-8 {{no viable conversion from 'const char8_t [9]' to 'string'}}
#endif
-
-template<bool b>
-struct C {
- explicit(C)(int);
-};
-#if __cplusplus <= 201703L
-// expected-warning@-3 {{this expression will be parsed as explicit(bool) in C++2a}}
-#if defined(__cpp_conditional_explicit)
-#error "the feature test macro __cpp_conditional_explicit isn't correct"
-#endif
-#else
-// expected-error@-8 {{does not refer to a value}}
-// expected-error@-9 {{expected member name or ';'}}
-// expected-error@-10 {{expected ')'}}
-// expected-note@-12 {{declared here}}
-// expected-note@-12 {{to match this '('}}
-#if !defined(__cpp_conditional_explicit) || __cpp_conditional_explicit != 201806L
-#error "the feature test macro __cpp_conditional_explicit isn't correct"
-#endif
-#endif
\ No newline at end of file
+++ /dev/null
-// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify
-
-template <bool b, auto val> struct enable_ifv {};
-
-template <auto val> struct enable_ifv<true, val> {
- static constexpr auto value = val;
-};
-
-template <typename T1, typename T2> struct is_same {
- static constexpr bool value = false;
-};
-
-template <typename T> struct is_same<T, T> {
- static constexpr bool value = true;
-};
-
-namespace special_cases
-{
-
-template<int a>
-struct A {
-// expected-note@-1+ {{candidate constructor}}
- explicit(1 << a)
-// expected-note@-1 {{negative shift count -1}}
-// expected-error@-2 {{explicit specifier argument is not a constant expression}}
- A(int);
-};
-
-A<-1> a(0);
-// expected-error@-1 {{no matching constructor}}
-// expected-note@-2 {{in instantiation of template class}}
-
-template<int a>
-struct B {
- explicit(b)
- // expected-error@-1 {{use of undeclared identifier}}
- B(int);
-};
-
-template<int a>
-struct B1 {
- explicit(a +)
- // expected-error@-1 {{expected expression}}
- B1(int);
-};
-
-struct B2 {
- explicit(false) explicit
- B2(int);
- // expected-error@-2 {{duplicate 'explicit' declaration specifier}}
-};
-
-template<int a>
- struct C {
- // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}}
- // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}}
- explicit(a == 0)
-C(int),
-C(double);
-};
-
-C<0> c0 = 0.0; // expected-error {{no viable conversion}}
-C<0> c1 = 0; // expected-error {{no viable conversion}}
-C<1> c2 = 0.0;
-C<1> c3 = 0;
-
-explicit(false) void f(int);// expected-error {{'explicit' can only be specified inside the class definition}}
-
-struct D {
- explicit(false) void f(int);// expected-error {{'explicit' can only be applied to a constructor or conversion function}}
-};
-
-template <typename T> struct E {
- // expected-note@-1+ {{candidate constructor}}
- explicit((T{}, false))
- // expected-error@-1 {{illegal initializer type 'void'}}
- E(int);
-};
-
-E<void> e = 1;
-// expected-error@-1 {{no viable conversion}}
-// expected-note@-2 {{in instantiation of}}
-
-}
-
-namespace trailling_object {
-
-template<bool b>
-struct B {
- explicit(b) B(int) {}
-};
-
-template<bool b>
-struct A : B<b> {
- explicit(b) A(int) : B<b>(0) {}
-};
-
-A<true> a(0);
-
-}
-
-namespace constructor1 {
-
-template<bool b>
- struct A {
- // expected-note@-1+ {{candidate constructor}}
- // expected-note@-2+ {{candidate function}}
- explicit(b) A(int, int = 0);
- // expected-note@-1+ {{explicit constructor declared here}}
-};
-
-template<bool b>
-A<b>::A(int, int) {}
-
-void f()
-{
-A<true> a0 = 0; // expected-error {{no viable conversion}}
-A<true> a1( 0);
-A<true> && a2 = 0;// expected-error {{could not bind}}
-A<true> && a3( 0);// expected-error {{could not bind}}
-A<true> a4{ 0};
-A<true> && a5 = { 0};// expected-error {{chosen constructor is explicit}}
-A<true> && a6{ 0};
-A<true> a7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-
-a0 = 0;
-a1 = { 0}; // expected-error {{no viable overloaded '='}}
-a2 = A<true>( 0);
-a3 = A<true>{ 0};
-
-A<false> c0 = ((short)0);
-A<false> c1( ((short)0));
-A<false> && c2 = ((short)0);
-A<false> && c3( ((short)0));
-A<false> c4{ ((short)0)};
-A<false> && c5 = { ((short)0)};
-A<false> && c6{ ((short)0)};
-
-A<true> d1( 0, 0);
-A<true> d2{ 0, 0};
-A<true> d3 = { 0, 0}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-
-d1 = { 0, 0}; // expected-error {{no viable overloaded '='}}
-d2 = A<true>( 0, 0);
-d3 = A<true>{ 0, 0};
-}
-}
-
-namespace constructor2 {
-
-template<bool a, typename T1>
-struct A {
- // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}}
- // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}}
- template<typename T2>
- explicit(a ^ is_same<T1, T2>::value)
- // expected-note@-1+ {{explicit(bool) specifier resolved to true}}
- A(T2) {}
- // expected-note@-1+ {{explicit constructor declared here}}
- // expected-note@-2+ {{candidate constructor ignored}}
-};
-
-A<true, int> a0 = 0.0; // expected-error {{no viable conversion}}
-A<true, int> a1( 0.0);
-A<true, int> && a2 = 0.0;// expected-error {{could not bind}}
-A<true, int> && a3( 0.0);// expected-error {{could not bind}}
-A<true, int> a4{ 0.0};
-A<true, int> && a5 = { 0.0};// expected-error {{chosen constructor is explicit}}
-A<true, int> && a6{ 0.0};
-A<true, int> a7 = { 0.0}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-
-A<true, int> b0 = 0;
-A<true, int> b1( 0);
-A<true, int> && b2 = 0;
-A<true, int> && b3( 0);
-A<true, int> b4{ 0};
-A<true, int> && b5 = { 0};
-A<true, int> && b6{ 0};
-A<true, int> b7 = { 0};
-
-A<true, double> c0 = 0; // expected-error {{no viable conversion}}
-A<true, double> c1( 0);
-A<true, double> && c2 = 0;// expected-error {{could not bind}}
-A<true, double> && c3( 0);// expected-error {{could not bind}}
-A<true, double> c4{ 0};
-A<true, double> && c5 = { 0};// expected-error {{chosen constructor is explicit}}
-A<true, double> && c6{ 0};
-A<true, double> c7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-
-}
-
-namespace constructor_sfinae {
-
-template<bool a>
-struct A {
- // expected-note@-1+ {{candidate constructor}}
- template<typename T>
- explicit(enable_ifv<is_same<int, T>::value, a>::value)
- //expected-note@-1 {{explicit(bool) specifier resolved to true}}
- A(T) {}
- // expected-note@-1+ {{substitution failure}}
- // expected-note@-2 {{candidate constructor ignored}}
- // expected-note@-3 {{explicit constructor declared here}}
- template<typename T, bool c = true>
- explicit(enable_ifv<is_same<bool, T>::value, a>::value)
- //expected-note@-1 {{explicit(bool) specifier resolved to true}}
- A(T) {}
- // expected-note@-1+ {{substitution failure}}
- // expected-note@-2 {{candidate constructor ignored}}
- // expected-note@-3 {{explicit constructor declared here}}
-};
-
-A<true> a0 = 0.0; // expected-error {{no viable conversion}}
-A<true> a1( 0.0); // expected-error {{no matching constructor}}
-A<true> a4{ 0.0}; // expected-error {{no matching constructor}}
-A<true> a7 = { 0.0}; // expected-error {{no matching constructor}}
-
-A<true> b0 = 0; // expected-error {{no viable conversion}}
-A<true> b1( 0);
-A<true> b4{ 0};
-A<true> b7 = { 0}; // expected-error {{chosen constructor is explicit}}
-
-A<false> c0 = 0;
-A<false> c1( 0);
-A<false> c4{ 0};
-A<false> c7 = { 0};
-
-A<true> d0 = true; // expected-error {{no viable conversion}}
-A<true> d1( true);
-A<true> d4{ true};
-A<true> d7 = { true}; // expected-error {{chosen constructor is explicit}}
-
-}
-
-namespace conversion {
-
-template<bool a>
-struct A {
- explicit(a) operator int ();
-};
-
-template<bool a>
-A<a>::operator int() {
- return 0;
-}
-
-A<true> A_true;
-A<false> A_false;
-
-int ai0 = A<true>(); // expected-error {{no viable conversion}}
-const int& ai1 = A<true>(); // expected-error {{no viable conversion}}
-int&& ai3 = A<true>(); // expected-error {{no viable conversion}}
-int ai4 = A_true; // expected-error {{no viable conversion}}
-const int& ai5 = A_true; // expected-error {{no viable conversion}}
-
-int ai01 = {A<true>()}; // expected-error {{no viable conversion}}
-const int& ai11 = {A<true>()}; // expected-error {{no viable conversion}}
-int&& ai31 = {A<true>()}; // expected-error {{no viable conversion}}
-int ai41 = {A_true}; // expected-error {{no viable conversion}}
-const int& ai51 = {A_true}; // expected-error {{no viable conversion}}
-
-int ae0(A<true>());
-const int& ae1(A<true>());
-int&& ae3(A<true>());
-int ae4(A_true);
-const int& ae5(A_true);
-
-int bi0 = A<false>();
-const int& bi1 = A<false>();
-int&& bi3 = A<false>();
-int bi4 = A_false;
-const int& bi5 = A_false;
-
-int bi01 = {A<false>()};
-const int& bi11 = {A<false>()};
-int&& bi31 = {A<false>()};
-int bi41 = {A_false};
-const int& bi51 = {A_false};
-
-int be0(A<true>());
-const int& be1(A<true>());
-int&& be3(A<true>());
-int be4(A_true);
-const int& be5(A_true);
-
-}
-
-namespace conversion2 {
-
-struct B {};
-// expected-note@-1+ {{candidate constructor}}
-template<bool a>
-struct A {
- template<typename T2>
- explicit(enable_ifv<is_same<B, T2>::value, a>::value)
- // expected-note@-1+ {{explicit(bool) specifier resolved to true}}
- operator T2() { return T2(); };
- // expected-note@-1+ {{substitution failure}}
- // expected-note@-2+ {{candidate conversion}}
-};
-
-A<false> A_false;
-A<true> A_true;
-
-int ai0 = A<true>(); // expected-error {{no viable conversion}}
-const int& ai1 = A<true>(); // expected-error {{no viable conversion}}
-int&& ai3 = A<true>(); // expected-error {{no viable conversion}}
-int ai4 = A_false; // expected-error {{no viable conversion}}
-const int& ai5 = A_false; // expected-error {{no viable conversion}}
-
-int ae0{A<true>()}; // expected-error {{no viable conversion}}
-const int& ae1{A<true>()}; // expected-error {{no viable conversion}}
-int&& ae3{A<true>()}; // expected-error {{no viable conversion}}
-int ae4{A_true}; // expected-error {{no viable conversion}}
-const int& ae5{A_true}; // expected-error {{no viable conversion}}
-
-int ap0((A<true>())); // expected-error {{no viable conversion}}
-const int& ap1((A<true>())); // expected-error {{no viable conversion}}
-int&& ap3((A<true>())); // expected-error {{no viable conversion}}
-int ap4(A_true); // expected-error {{no viable conversion}}
-const int& ap5(A_true); // expected-error {{no viable conversion}}
-
-B b0 = A<true>(); // expected-error {{no viable conversion}}
-const B & b1 = A<true>(); // expected-error {{no viable conversion}}
-B && b3 = A<true>(); // expected-error {{no viable conversion}}
-B b4 = A_true; // expected-error {{no viable conversion}}
-const B & b5 = A_true; // expected-error {{no viable conversion}}
-
-B be0(A<true>());
-const B& be1(A<true>());
-B&& be3(A<true>());
-B be4(A_true);
-const B& be5(A_true);
-
-B c0 = A<false>();
-const B & c1 = A<false>();
-B && c3 = A<false>();
-B c4 = A_false;
-const B & c5 = A_false;
-
-}
-
-namespace parameter_pack {
-
-template<typename T>
-struct A {
- // expected-note@-1+ {{candidate constructor}}
- // expected-note@-2+ {{candidate function}}
- template<typename ... Ts>
- explicit((is_same<T, Ts>::value && ...))
- // expected-note@-1 {{explicit(bool) specifier resolved to true}}
- A(Ts...);
- // expected-note@-1 {{candidate constructor}}
- // expected-note@-2 {{explicit constructor}}
-};
-
-template<typename T>
-template<typename ... Ts>
-A<T>::A(Ts ...) {}
-
-void f() {
-
-A<int> a0 = 0; // expected-error {{no viable conversion}}
-A<int> a1( 0, 1);
-A<int> a2{ 0, 1};
-A<int> a3 = { 0, 1}; // expected-error {{chosen constructor is explicit}}
-
-a1 = 0; // expected-error {{no viable overloaded '='}}
-a2 = { 0, 1}; // expected-error {{no viable overloaded '='}}
-
-A<double> b0 = 0;
-A<double> b1( 0, 1);
-A<double> b2{ 0, 1};
-A<double> b3 = { 0, 1};
-
-b1 = 0;
-b2 = { 0, 1};
-
-}
-
-}
-
-namespace deduction_guide {
-
-template<bool b>
-struct B {};
-
-B<true> b_true;
-B<false> b_false;
-
-template<typename T>
-struct nondeduced
-{
-using type = T;
-};
-
-template<typename T1, typename T2, bool b>
-struct A {
- // expected-note@-1+ {{candidate function}}
- explicit(false)
- A(typename nondeduced<T1>::type, typename nondeduced<T2>::type, typename nondeduced<B<b>>::type) {}
- // expected-note@-1+ {{candidate template ignored}}
-};
-
-template<typename T1, typename T2, bool b>
-explicit(enable_ifv<is_same<T1, T2>::value, b>::value)
-A(T1, T2, B<b>) -> A<T1, T2, b>;
-// expected-note@-1+ {{explicit deduction guide declared here}}
-// expected-note@-2+ {{candidate template ignored}}
-void f() {
-
-A a0( 0.0, 1, b_true); // expected-error {{no viable constructor or deduction guide}}
-A a1{ 0.0, 1, b_true}; // expected-error {{no viable constructor or deduction guide}}
-A a2 = { 0.0, 1, b_true}; // expected-error {{no viable constructor or deduction guide}}
-auto a4 = A( 0.0, 1, b_true); // expected-error {{no viable constructor or deduction guide}}
-auto a5 = A{ 0.0, 1, b_true}; // expected-error {{no viable constructor or deduction guide}}
-
-A b0( 0, 1, b_true);
-A b1{ 0, 1, b_true};
-A b2 = { 0, 1, b_true}; // expected-error {{explicit deduction guide for copy-list-initialization}}
-auto b4 = A( 0, 1, b_true);
-auto b5 = A{ 0, 1, b_true};
-b0 = { 0, 1, b_false}; // expected-error {{no viable overloaded '='}}
-
-A c0( 0, 1, b_false);
-A c1{ 0, 1, b_false};
-A c2 = { 0, 1, b_false};
-auto c4 = A( 0, 1, b_false);
-auto c5 = A{ 0, 1, b_false};
-c2 = { 0, 1, b_false};
-
-}
-
-}
-
-namespace test8 {
-
-template<bool b>
-struct A {
- //expected-note@-1+ {{candidate function}}
- template<typename T1, typename T2>
- explicit(b)
- A(T1, T2) {}
- //expected-note@-1 {{explicit constructor declared here}}
-};
-
-template<typename T1, typename T2>
-explicit(!is_same<T1, int>::value)
-A(T1, T2) -> A<!is_same<int, T2>::value>;
-// expected-note@-1+ {{explicit deduction guide declared here}}
-
-template<bool b>
-A<b> v();
-
-void f() {
-
-A a0( 0, 1);
-A a1{ 0, 1};
-A a2 = { 0, 1};
-auto a4 = A( 0, 1);
-auto a5 = A{ 0, 1};
-auto a6(v<false>());
-a6 = { 0, 1};
-
-A b0( 0.0, 1);
-A b1{ 0.0, 1};
-A b2 = { 0.0, 1}; // expected-error {{explicit deduction guide for copy-list-initialization}}
-auto b4 = A( 0.0, 1);
-auto b5 = A{ 0.0, 1};
-
-A c0( 0, 1.0);
-A c1{ 0, 1.0};
-A c2 = { 0, 1.0}; // expected-error {{chosen constructor is explicit}}
-auto c4 = A( 0, 1.0);
-auto c5 = A{ 0, 1.0};
-auto c6(v<true>());
-c0 = { 0, 1.0}; // expected-error {{no viable overloaded '='}}
-
-A d0( 0.0, 1.0);
-A d1{ 0.0, 1.0};
-A d2 = { 0.0, 1.0}; // expected-error {{explicit deduction guide for copy-list-initialization}}
-auto d4 = A( 0.0, 1.0);
-auto d5 = A{ 0.0, 1.0};
-
-}
-
-}
-
-namespace conversion3 {
-
-template<bool b>
-struct A {
- explicit(!b) operator int();
- explicit(b) operator bool();
-};
-
-template<bool b>
-A<b>::operator bool() { return false; }
-
-struct B {
- void f(int);
- void f(bool);
-};
-
-void f(A<true> a, B b) {
- b.f(a);
-}
-
-void f1(A<false> a, B b) {
- b.f(a);
-}
-
-// Taken from 12.3.2p2
-class X { X(); };
-class Y { }; // expected-note+ {{candidate constructor (the implicit}}
-
-template<bool b>
-struct Z {
- explicit(b) operator X() const;
- explicit(b) operator Y() const;
- explicit(b) operator int() const;
-};
-
-void testExplicit()
-{
-Z<true> z;
-// 13.3.1.4p1 & 8.5p16:
-Y y2 = z; // expected-error {{no viable conversion}}
-Y y2b(z);
-Y y3 = (Y)z;
-Y y4 = Y(z);
-Y y5 = static_cast<Y>(z);
-// 13.3.1.5p1 & 8.5p16:
-int i1 = (int)z;
-int i2 = int(z);
-int i3 = static_cast<int>(z);
-int i4(z);
-// 13.3.1.6p1 & 8.5.3p5:
-const Y& y6 = z; // expected-error {{no viable conversion}}
-const int& y7 = z; // expected-error {{no viable conversion}}
-const Y& y8(z);
-const int& y9(z);
-
-// Y is an aggregate, so aggregate-initialization is performed and the
-// conversion function is not considered.
-const Y y10{z}; // expected-error {{excess elements}}
-const Y& y11{z}; // expected-error {{excess elements}} expected-note {{in initialization of temporary}}
-const int& y12{z};
-
-// X is not an aggregate, so constructors are considered,
-// per 13.3.3.1/4 & DR1467.
-const X x1{z};
-const X& x2{z};
-}
-
-struct tmp {};
-
-template<typename T1>
-struct C {
- template<typename T>
- explicit(!is_same<T1, T>::value)
- // expected-note@-1+ {{explicit(bool) specifier resolved to true}}
- operator T();
- // expected-note@-1+ {{candidate conversion operator ignored}}
-};
-
-using Bool = C<bool>;
-using Integral = C<int>;
-using Unrelated = C<tmp>;
-
-void testBool() {
-Bool b;
-Integral n;
-Unrelated u;
-
-(void) (1 + b); // expected-error {{invalid operands to binary expression}}
-(void) (1 + n);
-(void) (1 + u); // expected-error {{invalid operands to binary expression}}
-
-// 5.3.1p9:
-(void) (!b);
-(void) (!n);
-(void) (!u);
-
-// 5.14p1:
-(void) (b && true);
-(void) (n && true);
-(void) (u && true);
-
-// 5.15p1:
-(void) (b || true);
-(void) (n || true);
-(void) (u || true);
-
-// 5.16p1:
-(void) (b ? 0 : 1);
-(void) (n ? 0: 1);
-(void) (u ? 0: 1);
-
-// // 5.19p5:
-// // TODO: After constexpr has been implemented
-
-// 6.4p4:
-if (b) {}
-if (n) {}
-if (u) {}
-
-// 6.4.2p2:
-switch (b) {} // expected-error {{statement requires expression of integer type}}
-switch (n) {} // expected-error {{statement requires expression of integer type}}
-switch (u) {} // expected-error {{statement requires expression of integer type}}
-
-// 6.5.1:
-while (b) {}
-while (n) {}
-while (u) {}
-
-// 6.5.2p1:
-do {} while (b);
-do {} while (n);
-do {} while (u);
-
-// 6.5.3:
-for (;b;) {}
-for (;n;) {}
-for (;u;) {}
-
-// 13.3.1.5p1:
-bool db1(b);
-bool db2(n);
-bool db3(u);
-int di1(b);
-int di2(n);
-int di3(n);
-const bool &direct_cr1(b);
-const bool &direct_cr2(n);
-const bool &direct_cr3(n);
-const int &direct_cr4(b);
-const int &direct_cr5(n);
-const int &direct_cr6(n);
-bool directList1{b};
-bool directList2{n};
-bool directList3{n};
-int directList4{b};
-int directList5{n};
-int directList6{n};
-const bool &directList_cr1{b};
-const bool &directList_cr2{n};
-const bool &directList_cr3{n};
-const int &directList_cr4{b};
-const int &directList_cr5{n};
-const int &directList_cr6{n};
-bool copy1 = b;
-bool copy2 = n;// expected-error {{no viable conversion}}
-bool copyu2 = u;// expected-error {{no viable conversion}}
-int copy3 = b;// expected-error {{no viable conversion}}
-int copy4 = n;
-int copyu4 = u;// expected-error {{no viable conversion}}
-const bool ©5 = b;
-const bool ©6 = n;// expected-error {{no viable conversion}}
-const bool ©u6 = u;// expected-error {{no viable conversion}}
-const int ©7 = b;// expected-error {{no viable conversion}}
-const int ©8 = n;
-const int ©u8 = u;// expected-error {{no viable conversion}}
-bool copyList1 = {b};
-bool copyList2 = {n};// expected-error {{no viable conversion}}
-bool copyListu2 = {u};// expected-error {{no viable conversion}}
-int copyList3 = {b};// expected-error {{no viable conversion}}
-int copyList4 = {n};
-int copyListu4 = {u};// expected-error {{no viable conversion}}
-const bool ©List5 = {b};
-const bool ©List6 = {n};// expected-error {{no viable conversion}}
-const bool ©Listu6 = {u};// expected-error {{no viable conversion}}
-const int ©List7 = {b};// expected-error {{no viable conversion}}
-const int ©List8 = {n};
-const int ©Listu8 = {u};// expected-error {{no viable conversion}}
-}
-
-}
-
-namespace deduction_guide2 {
-
-template<typename T1 = int, typename T2 = int>
-struct A {
- // expected-note@-1+ {{candidate template ignored}}
- explicit(!is_same<T1, T2>::value)
- // expected-note@-1+ {{explicit(bool) specifier resolved to true}}
- A(T1 = 0, T2 = 0) {}
- // expected-note@-1 {{explicit constructor}}
- // expected-note@-2+ {{candidate deductiong guide ignored}}
-};
-
-A a0 = 0;
-A a1(0, 0);
-A a2{0, 0};
-A a3 = {0, 0};
-
-A b0 = 0.0; // expected-error {{no viable constructor or deduction guide}}
-A b1(0.0, 0.0);
-A b2{0.0, 0.0};
-A b3 = {0.0, 0.0};
-
-A b4 = {0.0, 0}; // expected-error {{explicit constructor}}
-
-template<typename T1, typename T2>
-explicit A(T1, T2) -> A<T1, T2>;
-// expected-note@-1+ {{explicit deduction guide}}
-
-A c0 = 0;
-A c1(0, 0);
-A c2{0, 0};
-A c3 = {0, 0};// expected-error {{explicit deduction guide}}
-
-A d0 = 0.0; // expected-error {{no viable constructor or deduction guide}}
-A d1(0, 0);
-A d2{0, 0};
-A d3 = {0.0, 0.0};// expected-error {{explicit deduction guide}}
-
-}
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s
-
namespace Constructor {
struct A {
A(int);
const int ©List7 = {b};
const int ©List8 = {n}; // expected-error {{no viable conversion}}
}
-
-#if __cplusplus < 201707L
+
void testNew()
{
// 5.3.4p6:
new int[i];
new int[ni]; // expected-error {{array size expression of type 'NotInt' requires explicit conversion to type 'int'}}
}
-#endif
-
+
void testDelete()
{
// 5.3.5pp2:
case Lang_CXX14:
BasicArgs = {"-std=c++14", "-frtti"};
break;
- case Lang_CXX2a:
- BasicArgs = {"-std=c++2a", "-frtti"};
- break;
case Lang_OpenCL:
case Lang_OBJCXX:
llvm_unreachable("Not implemented yet!");
Lang_CXX,
Lang_CXX11,
Lang_CXX14,
- Lang_CXX2a,
Lang_OpenCL,
Lang_OBJCXX
};
Args.push_back("-std=c++14");
FileName = "input.cc";
break;
- case Lang_CXX2a:
- Args.push_back("-std=c++2a");
- FileName = "input.cc";
- break;
case Lang_OpenCL:
FileName = "input.cl";
break;
EXPECT_FALSE(testStructuralMatch(t));
}
-TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {
- auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};",
- "struct foo {explicit(true) foo(int);};", Lang_CXX2a);
- CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<0>(Decls), cxxConstructorDecl(hasName("foo")));
- CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<1>(Decls), cxxConstructorDecl(hasName("foo")));
- EXPECT_FALSE(testStructuralMatch(First, Second));
-}
-
-TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {
- auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};",
- "struct foo {explicit(true) foo(int);};", Lang_CXX2a);
- CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<0>(Decls), cxxConstructorDecl(hasName("foo")));
- CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<1>(Decls), cxxConstructorDecl(hasName("foo")));
- EXPECT_TRUE(testStructuralMatch(First, Second));
-}
-
struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
EXPECT_FALSE(testStructuralMatch(t));
}
-TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
- auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};",
- "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX2a);
- CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
- CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
- EXPECT_TRUE(testStructuralMatch(First, Second));
-}
-
-TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {
- auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};",
- "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX2a);
- CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));
- CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(
- get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));
- EXPECT_FALSE(testStructuralMatch(First, Second));
-}
-
} // end namespace ast_matchers
} // end namespace clang
<tr>
<td><tt>explicit(bool)</tt></td>
<td><a href="http://wg21.link/p0892r2">P0892R2</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="none" align="center">No</td>
</tr>
<!-- San Diego papers -->
<tr>
if (is_artificial)
return nullptr; // skip everything artificial
- const clang::ExplicitSpecifier explicit_spec(
- nullptr /*expr*/, is_explicit
- ? clang::ExplicitSpecKind::ResolvedTrue
- : clang::ExplicitSpecKind::ResolvedFalse);
if (name[0] == '~') {
cxx_dtor_decl = clang::CXXDestructorDecl::Create(
*getASTContext(), cxx_record_decl, clang::SourceLocation(),
clang::SourceLocation()),
method_qual_type,
nullptr, // TypeSourceInfo *
- explicit_spec, is_inline, is_artificial, false /*is_constexpr*/);
+ is_explicit, is_inline, is_artificial, false /*is_constexpr*/);
cxx_method_decl = cxx_ctor_decl;
} else {
clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
clang::SourceLocation()),
method_qual_type,
nullptr, // TypeSourceInfo *
- is_inline, explicit_spec, false /*is_constexpr*/,
+ is_inline, is_explicit, false /*is_constexpr*/,
clang::SourceLocation());
}
}