From d2b9fc88c8c4c758068da680cd0e42e6ca41ffcd Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 6 May 2019 09:51:10 +0000 Subject: [PATCH] Revert r359949 "[clang] adding explicit(bool) from c++2a" MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This caused Clang to start erroring on the following: struct S {   template explicit S(); }; struct T : S {}; struct U : T {   U(); }; U::U() {} $ clang -c /tmp/x.cc /tmp/x.cc:10:4: error: call to implicitly-deleted default constructor of 'T' U::U() {}    ^ /tmp/x.cc:5:12: note: default constructor of 'T' is implicitly deleted because base class 'S' has no default constructor struct T : S {};            ^ 1 error generated. See discussion on the cfe-commits email thread. This also reverts the follow-ups r359966 and r359968. > this patch adds support for the explicit bool specifier. > > Changes: > - The parsing for the explicit(bool) specifier was added in ParseDecl.cpp. > - The storage of the explicit specifier was changed. the explicit specifier was stored as a boolean value in the FunctionDeclBitfields and in the DeclSpec class. now it is stored as a PointerIntPair with a flag and a potential expression in CXXConstructorDecl, CXXDeductionGuideDecl, CXXConversionDecl and in the DeclSpec class. > - Following the AST change, Serialization, ASTMatchers, ASTComparator and ASTPrinter were adapted. > - Template instantiation was adapted to instantiate the potential expressions of the explicit(bool) specifier When instantiating their associated declaration. > - The Add*Candidate functions were adapted, they now take a Boolean indicating if the context allowing explicit constructor or conversion function and this boolean is used to remove invalid overloads that required template instantiation to be detected. > - Test for Semantic and Serialization were added. > > This patch is not yet complete. I still need to check that interaction with CTAD and deduction guides is correct. and add more tests for AST operations. But I wanted first feedback. > Perhaps this patch should be spited in smaller patches, but making each patch testable as a standalone may be tricky. > > Patch by Tyker > > Differential Revision: https://reviews.llvm.org/D60934 llvm-svn: 360024 --- clang/include/clang/AST/Decl.h | 10 + clang/include/clang/AST/DeclBase.h | 20 +- clang/include/clang/AST/DeclCXX.h | 176 ++--- clang/include/clang/ASTMatchers/ASTMatchers.h | 3 - clang/include/clang/Basic/DiagnosticCommonKinds.td | 2 - clang/include/clang/Basic/DiagnosticParseKinds.td | 4 - clang/include/clang/Basic/DiagnosticSemaKinds.td | 13 +- clang/include/clang/Basic/Specifiers.h | 8 - clang/include/clang/Sema/DeclSpec.h | 62 +- clang/include/clang/Sema/Overload.h | 5 - clang/include/clang/Sema/Sema.h | 38 +- clang/include/clang/Serialization/ASTBitCodes.h | 3 + clang/include/clang/Serialization/ASTReader.h | 8 - clang/lib/AST/ASTImporter.cpp | 28 +- clang/lib/AST/ASTStructuralEquivalence.cpp | 6 +- clang/lib/AST/Decl.cpp | 1 + clang/lib/AST/DeclCXX.cpp | 109 ++-- clang/lib/AST/DeclPrinter.cpp | 22 +- clang/lib/Frontend/InitPreprocessor.cpp | 2 - clang/lib/Parse/ParseDecl.cpp | 62 +- clang/lib/Sema/DeclSpec.cpp | 28 +- clang/lib/Sema/SemaCodeComplete.cpp | 6 +- clang/lib/Sema/SemaDecl.cpp | 18 +- clang/lib/Sema/SemaDeclCXX.cpp | 59 +- clang/lib/Sema/SemaInit.cpp | 88 ++- clang/lib/Sema/SemaLambda.cpp | 4 +- clang/lib/Sema/SemaLookup.cpp | 9 +- clang/lib/Sema/SemaOverload.cpp | 173 ++--- clang/lib/Sema/SemaTemplate.cpp | 16 +- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 53 +- clang/lib/Serialization/ASTReaderDecl.cpp | 9 +- clang/lib/Serialization/ASTWriter.cpp | 1 + clang/lib/Serialization/ASTWriterDecl.cpp | 24 +- clang/test/CXX/temp/temp.deduct.guide/p1.cpp | 2 +- clang/test/CXX/temp/temp.deduct.guide/p3.cpp | 8 +- clang/test/PCH/cxx-explicit-specifier.cpp | 124 ---- .../test/SemaCXX/builtin-is-constant-evaluated.cpp | 2 +- clang/test/SemaCXX/cxx2a-compat.cpp | 20 - clang/test/SemaCXX/cxx2a-explicit-bool.cpp | 719 --------------------- clang/test/SemaCXX/explicit.cpp | 8 +- clang/unittests/AST/Language.cpp | 3 - clang/unittests/AST/Language.h | 1 - clang/unittests/AST/MatchVerifier.h | 4 - clang/unittests/AST/StructuralEquivalenceTest.cpp | 40 -- clang/www/cxx_status.html | 2 +- lldb/source/Symbol/ClangASTContext.cpp | 8 +- 46 files changed, 362 insertions(+), 1649 deletions(-) delete mode 100644 clang/test/PCH/cxx-explicit-specifier.cpp delete mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool.cpp diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index cfb9ff8..da81289 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2369,6 +2369,16 @@ public: /// 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; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index ad283a6..64adf30 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1472,6 +1472,10 @@ class DeclContext { 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; @@ -1519,7 +1523,7 @@ class DeclContext { }; /// Number of non-inherited bits in FunctionDeclBitfields. - enum { NumFunctionDeclBits = 24 }; + enum { NumFunctionDeclBits = 25 }; /// Stores the bits used by CXXConstructorDecl. If modified /// NumCXXConstructorDeclBits and the accessor @@ -1531,25 +1535,17 @@ class DeclContext { /// 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 diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index b8a4c1b..0d4b035 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1993,50 +1993,6 @@ public: } }; -/// Store information needed for an explicit specifier. -/// used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl. -class ExplicitSpecifier { - llvm::PointerIntPair 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 @@ -2052,36 +2008,31 @@ class CXXDeductionGuideDecl : public FunctionDecl { 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 { @@ -2550,8 +2501,7 @@ public: /// \endcode class CXXConstructorDecl final : public CXXMethodDecl, - private llvm::TrailingObjects { + private llvm::TrailingObjects { // This class stores some data in DeclContext::CXXConstructorDeclBits // to save some space. Use the provided accessors to access it. @@ -2561,74 +2511,28 @@ class CXXConstructorDecl final 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) const { - return CXXConstructorDeclBits.IsInheritingConstructor; - } - size_t numTrailingObjects(OverloadToken) const { - return CXXConstructorDeclBits.HasTrailingExplicitSpecifier; - } - - ExplicitSpecifier getExplicitSpecifierInternal() const { - if (CXXConstructorDeclBits.HasTrailingExplicitSpecifier) - return *getCanonicalDecl()->getTrailingObjects(); - 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() = ES; - else - CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit(); - } - - enum TraillingAllocKind { - TAKInheritsConstructor = 1, - TAKHasTailExplicit = 1 << 1, - }; - - uint64_t getTraillingAllocKind() const { - return numTrailingObjects(OverloadToken()) | - (numTrailingObjects(OverloadToken()) << 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 **; @@ -2699,6 +2603,11 @@ public: 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) && @@ -2877,39 +2786,34 @@ public: 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()->getReturnType(); diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index d973b48..0e4b9f7 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -6171,9 +6171,6 @@ AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) { 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(); } diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 0727980..7cd3b21 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -150,8 +150,6 @@ def ext_warn_duplicate_declspec : ExtWarn<"%sub{duplicate_declspec}0">, def warn_duplicate_declspec : Warning<"%sub{duplicate_declspec}0">, InGroup; -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< diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 06b7296..84069e4 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -33,10 +33,6 @@ def err_asm_goto_not_supported_yet : 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, DefaultIgnore; - def ext_empty_translation_unit : Extension< "ISO C requires a translation unit to contain at least one declaration">, InGroup>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 64d8632..34f4534 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -83,11 +83,11 @@ def err_typecheck_converted_constant_expression_indirect : Error< "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, DefaultError, SFINAEFailure; @@ -2115,8 +2115,9 @@ def err_deduction_guide_wrong_scope : Error< "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< @@ -3639,10 +3640,6 @@ def note_ovl_candidate : Note< "| 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< diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index cc0c1c8..7256aca 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -20,14 +20,6 @@ #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, diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index f1c2a67..babdc9d 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -22,7 +22,6 @@ #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" @@ -357,6 +356,7 @@ private: 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 @@ -371,9 +371,6 @@ private: Expr *ExprRep; }; - /// ExplicitSpecifier - Store information about explicit spicifer. - ExplicitSpecifier FS_explicit_specifier; - // attributes. ParsedAttributes Attrs; @@ -396,7 +393,6 @@ private: 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; @@ -424,18 +420,31 @@ public: } 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; } @@ -561,22 +570,11 @@ public: 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; } @@ -588,9 +586,8 @@ public: 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(); } @@ -709,8 +706,7 @@ public: 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); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index cacb592..342ce0f 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -705,11 +705,6 @@ class Sema; /// 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, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 74de4f5..af85e23 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2734,8 +2734,7 @@ public: 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); @@ -2858,7 +2857,6 @@ public: bool SuppressUserConversions = false, bool PartialOverloading = false, bool AllowExplicit = false, - bool AllowExplicitConversion = false, ADLCallKind IsADLCandidate = ADLCallKind::NotADL, ConversionSequenceList EarlyConversions = None); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, @@ -2897,7 +2895,7 @@ public: FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false, bool AllowExplicit = false, + bool PartialOverloading = false, ADLCallKind IsADLCandidate = ADLCallKind::NotADL); bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate, ArrayRef ParamTypes, @@ -2909,16 +2907,20 @@ public: 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, @@ -10116,14 +10118,6 @@ public: 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); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index b38b6b0..0365e3a 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1438,6 +1438,9 @@ namespace serialization { /// A CXXConstructorDecl record. DECL_CXX_CONSTRUCTOR, + /// A CXXConstructorDecl record for an inherited constructor. + DECL_CXX_INHERITED_CONSTRUCTOR, + /// A CXXDestructorDecl record. DECL_CXX_DESTRUCTOR, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 579cdc1..423313e 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -2430,14 +2430,6 @@ public: ID); } - ExplicitSpecifier readExplicitSpec() { - uint64_t Kind = readInt(); - bool HasExpr = Kind & 0x1; - Kind = Kind >> 1; - return ExplicitSpecifier(HasExpr ? readExpr() : nullptr, - static_cast(Kind)); - } - void readExceptionSpec(SmallVectorImpl &ExceptionStorage, FunctionProtoType::ExceptionSpecInfo &ESI) { return Reader->readExceptionSpec(*F, ExceptionStorage, ESI, Record, Idx); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 1ab99be..1ac4870 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3055,20 +3055,11 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Create the imported function. FunctionDecl *ToFunction = nullptr; if (auto *FromConstructor = dyn_cast(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( - ToFunction, D, Importer.getToContext(), cast(DC), - ToInnerLocStart, NameInfo, T, TInfo, - ExplicitSpecifier( - ExplicitExpr, - FromConstructor->getExplicitSpecifier().getKind()), - D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) + ToFunction, D, Importer.getToContext(), cast(DC), + ToInnerLocStart, NameInfo, T, TInfo, + FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast(D)) { @@ -3094,19 +3085,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast(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( ToFunction, D, Importer.getToContext(), cast(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(D)) { if (GetImportedOrCreateDecl( diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index f3c34d7..71bbd82 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -955,15 +955,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (auto *Constructor1 = dyn_cast(Method1)) { auto *Constructor2 = cast(Method2); - if (!Constructor1->getExplicitSpecifier().isEquivalent( - Constructor2->getExplicitSpecifier())) + if (Constructor1->isExplicit() != Constructor2->isExplicit()) return false; } if (auto *Conversion1 = dyn_cast(Method1)) { auto *Conversion2 = cast(Method2); - if (!Conversion1->getExplicitSpecifier().isEquivalent( - Conversion2->getExplicitSpecifier())) + if (Conversion1->isExplicit() != Conversion2->isExplicit()) return false; if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(), Conversion2->getConversionType())) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 499a451..19fd388 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2713,6 +2713,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.SClass = S; FunctionDeclBits.IsInline = isInlineSpecified; FunctionDeclBits.IsInlineSpecified = isInlineSpecified; + FunctionDeclBits.IsExplicitSpecified = false; FunctionDeclBits.IsVirtualAsWritten = false; FunctionDeclBits.IsPure = false; FunctionDeclBits.HasInheritedPrototype = false; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index b9ecdc6..d7eae5a 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1879,47 +1879,19 @@ bool CXXRecordDecl::mayBeAbstract() const { 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(Function)->getExplicitSpecifier(); - case Decl::Kind::CXXConversion: - return cast(Function)->getExplicitSpecifier(); - case Decl::Kind::CXXDeductionGuide: - return cast(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() {} @@ -2357,54 +2329,47 @@ SourceRange CXXCtorInitializer::getSourceRange() const { 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(Inherited)); setImplicit(isImplicitlyDeclared); - CXXConstructorDeclBits.HasTrailingExplicitSpecifier = ES.getExpr() ? 1 : 0; if (Inherited) *getTrailingObjects() = Inherited; - setExplicitSpecifier(ES); + setExplicitSpecified(isExplicitSpecified); } void CXXConstructorDecl::anchor() {} CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID, - uint64_t AllocKind) { - bool hasTraillingExplicit = static_cast(AllocKind & TAKHasTailExplicit); - bool isInheritingConstructor = - static_cast(AllocKind & TAKInheritsConstructor); - unsigned Extra = - additionalSizeToAlloc( - isInheritingConstructor, hasTraillingExplicit); + bool Inherited) { + unsigned Extra = additionalSizeToAlloc(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( - 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(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 { @@ -2555,21 +2520,25 @@ void CXXConversionDecl::anchor() {} 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 { diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 78a7afd..325400e 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -566,21 +566,6 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { } } -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()) @@ -611,9 +596,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 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); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 5aa2ea3..b0fb124 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -540,8 +540,6 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, 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"); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f883ecc..c4f02b9 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2442,12 +2442,12 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, 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(); @@ -2965,13 +2965,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, 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 . @@ -3522,34 +3518,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, 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(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); @@ -3893,32 +3864,25 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // 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(); diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index df27922..4f3e2fa 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -445,7 +445,7 @@ unsigned DeclSpec::getParsedSpecifiers() const { 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; @@ -944,24 +944,17 @@ bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc, } 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; } @@ -1300,26 +1293,23 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // 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(); } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index d86668c..c2d8040 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -4961,15 +4961,13 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, CandidateSet, /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true, - /*AllowExplicit*/ true); + /*PartialOverloading=*/true); } else if (auto *FTD = dyn_cast(C)) { AddTemplateOverloadCandidate( FTD, DeclAccessPair::make(FTD, C->getAccess()), /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true, - /*AllowExplicit*/ true); + /*PartialOverloading=*/true); } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 86b5645..379e2ae 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5705,7 +5705,7 @@ void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function); - if (DS.hasExplicitSpecifier()) + if (DS.isExplicitSpecified()) Diag(DS.getExplicitSpecLoc(), diag::err_explicit_non_function); @@ -7969,7 +7969,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, 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. @@ -7989,7 +7989,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, R = SemaRef.CheckConstructorDeclarator(D, R, SC); return CXXConstructorDecl::Create( SemaRef.Context, cast(DC), D.getBeginLoc(), NameInfo, R, - TInfo, ExplicitSpecifier, isInline, + TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false, isConstexpr); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { @@ -8034,13 +8034,13 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, IsVirtualOkay = true; return CXXConversionDecl::Create( SemaRef.Context, cast(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, @@ -8401,7 +8401,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, 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()) { @@ -8584,20 +8584,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // 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(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(NewFD) && !isa(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()); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8ddc5f1..7e4aab0 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -657,13 +657,14 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, 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(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(New); + if (NewGuide && NewGuide->isExplicitSpecified() != + cast(Old)->isExplicitSpecified()) { + Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch) + << NewGuide->isExplicitSpecified(); Diag(Old->getLocation(), diag::note_previous_declaration); } @@ -8591,12 +8592,12 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, 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 @@ -10819,28 +10820,6 @@ struct ComputingExceptionSpec { }; } -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, @@ -10989,9 +10968,9 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( = 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(); @@ -11110,7 +11089,7 @@ Sema::findInheritingConstructor(SourceLocation Loc, 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()) @@ -12562,9 +12541,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // 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(); @@ -12693,9 +12671,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // 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(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 5b78d44..e8a8887 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3763,10 +3763,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, 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 @@ -3780,8 +3779,8 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, hasCopyOrMoveCtorParam(S.Context, Info); S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, CandidateSet, SuppressUserConversions, - /*PartialOverloading=*/false, AllowExplicit, - AllowExplicitConv); + /*PartialOverloading=*/false, + /*AllowExplicit=*/AllowExplicitConv); } } @@ -3814,17 +3813,16 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, else Conv = cast(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); } } } @@ -4370,16 +4368,14 @@ static OverloadingResult TryRefInitWithConversionFunction( 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); } } } @@ -4414,17 +4410,17 @@ static OverloadingResult TryRefInitWithConversionFunction( // 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); } } } @@ -5000,16 +4996,14 @@ static void TryUserDefinedConversion(Sema &S, 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); } } } @@ -5044,12 +5038,12 @@ static void TryUserDefinedConversion(Sema &S, 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); } } @@ -9342,7 +9336,6 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( OverloadCandidateSet::iterator Best; bool HasAnyDeductionGuide = false; - bool AllowExplicit = !Kind.isCopyInit() || ListInit; auto tryToResolveOverload = [&](bool OnlyListConstructors) -> OverloadingResult { @@ -9368,7 +9361,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // 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; @@ -9403,9 +9396,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( 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); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 1966e9e..b686681 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1325,7 +1325,7 @@ static void addFunctionPointerConversion(Sema &S, 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); @@ -1412,7 +1412,7 @@ static void addBlockPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/true, ExplicitSpecifier(), + /*isInline=*/true, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index a91c20e..2b7924d 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3041,15 +3041,10 @@ Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD, 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(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1ef932e..df979b6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3242,13 +3242,10 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, 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); } } @@ -3375,15 +3372,13 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, 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); } } } @@ -3415,13 +3410,14 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, 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); } } } @@ -4449,13 +4445,13 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, } 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); @@ -5418,7 +5414,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, // 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, @@ -5734,13 +5730,12 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType, 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); } } @@ -5992,11 +5987,13 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, /// \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 Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, - ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions) { +void Sema::AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, ArrayRef Args, + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions, + bool PartialOverloading, bool AllowExplicit, + ADLCallKind IsADLCandidate, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast(Function->getType()->getAs()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6153,11 +6150,13 @@ void Sema::AddOverloadCandidate( // (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; @@ -6171,15 +6170,6 @@ void Sema::AddOverloadCandidate( } } - 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; @@ -6769,7 +6759,7 @@ void Sema::AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate) { + bool PartialOverloading, ADLCallKind IsADLCandidate) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; @@ -6818,10 +6808,9 @@ void Sema::AddTemplateOverloadCandidate( // 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 @@ -6926,11 +6915,14 @@ static bool isAllowableExplicitConversion(Sema &S, /// 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(); @@ -7089,13 +7081,6 @@ void Sema::AddConversionCandidate( "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; @@ -7115,11 +7100,14 @@ void Sema::AddConversionCandidate( /// 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(FunctionTemplate->getTemplatedDecl()) && "Only conversion function templates permitted here"); @@ -7149,7 +7137,7 @@ void Sema::AddTemplateConversionCandidate( assert(Specialization && "Missing function template specialization?"); AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, CandidateSet, AllowObjCConversionOnExplicit, - AllowExplicit, AllowResultConversion); + AllowResultConversion); } /// AddSurrogateCandidate - Adds a "surrogate" candidate function that @@ -9003,14 +8991,12 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, /*SupressUserConversions=*/false, PartialOverloading, - /*AllowExplicitConversions*/ false, - /*AllowExplicit*/ false, ADLCallKind::UsesADL); + /*AllowExplicit=*/false, ADLCallKind::UsesADL); } else { - AddTemplateOverloadCandidate( - cast(*I), FoundDecl, ExplicitTemplateArgs, Args, - CandidateSet, - /*SupressUserConversions=*/false, PartialOverloading, - /*AllowExplicit*/ false, ADLCallKind::UsesADL); + AddTemplateOverloadCandidate(cast(*I), FoundDecl, + ExplicitTemplateArgs, Args, CandidateSet, + /*SupressUserConversions=*/false, + PartialOverloading, ADLCallKind::UsesADL); } } } @@ -10341,33 +10327,6 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) { << 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(Cand->Function)->getExplicitSpecifier(); - DeclName = "constructor"; - break; - case Decl::Kind::CXXConversion: - ES = cast(Cand->Function)->getExplicitSpecifier(); - DeclName = "conversion operator"; - break; - case Decl::Kind::CXXDeductionGuide: - ES = cast(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; @@ -10452,9 +10411,6 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, 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); @@ -13025,11 +12981,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Microsoft supports direct constructor calls. if (getLangOpts().MicrosoftExt && isa(Func)) { - AddOverloadCandidate(cast(Func), I.getPair(), Args, - CandidateSet, - /*SuppressUserConversions*/ false, - /*PartialOverloading*/ false, - /*AllowExplicit*/ true); + AddOverloadCandidate(cast(Func), I.getPair(), + Args, CandidateSet); } else if ((Method = dyn_cast(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b2f80eb..58ad439 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1109,7 +1109,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, if (DS.isVirtualSpecified()) EmitDiag(DS.getVirtualSpecLoc()); - if (DS.hasExplicitSpecifier()) + if (DS.isExplicitSpecified()) EmitDiag(DS.getExplicitSpecLoc()); if (DS.isNoreturnSpecified()) @@ -1789,8 +1789,8 @@ struct ConvertConstructorToDeductionGuideTransform { 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()); } @@ -1819,8 +1819,8 @@ struct ConvertConstructorToDeductionGuideTransform { Params.push_back(NewParam); } - return buildDeductionGuide(Template->getTemplateParameters(), - ExplicitSpecifier(), TSI, Loc, Loc, Loc); + return buildDeductionGuide(Template->getTemplateParameters(), false, TSI, + Loc, Loc, Loc); } private: @@ -1970,7 +1970,7 @@ private: } NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams, - ExplicitSpecifier ES, TypeSourceInfo *TInfo, + bool Explicit, TypeSourceInfo *TInfo, SourceLocation LocStart, SourceLocation Loc, SourceLocation LocEnd) { DeclarationNameInfo Name(DeductionGuideName, Loc); @@ -1979,8 +1979,8 @@ private: // 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); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 1c7341d..653eb69 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -366,29 +366,6 @@ static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( 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) { @@ -1713,14 +1690,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, cast(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); - ExplicitSpecifier InstantiatedExplicitSpecifier; - if (auto *DGuide = dyn_cast(D)) { - InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( - SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; - } - SmallVector Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -1758,9 +1727,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionDecl *Function; if (auto *DGuide = dyn_cast(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(Function)->setIsCopyDeductionCandidate(); Function->setAccess(D->getAccess()); @@ -2028,12 +1996,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } } - ExplicitSpecifier InstantiatedExplicitSpecifier = - instantiateExplicitSpecifier(SemaRef, TemplateArgs, - ExplicitSpecifier::getFromDecl(D), D); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; - SmallVector Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -2073,10 +2035,11 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast(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(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, @@ -2087,7 +2050,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } else if (CXXConversionDecl *Conversion = dyn_cast(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; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 27fcc9e..ffe0e8b 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -858,6 +858,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setStorageClass(static_cast(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()); @@ -1976,7 +1977,6 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { } void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { - D->setExplicitSpecifier(Record.readExplicitSpec()); VisitFunctionDecl(D); D->setIsCopyDeductionCandidate(Record.readInt()); } @@ -2002,7 +2002,6 @@ void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { 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(); auto *Ctor = ReadDeclAs(); @@ -2028,7 +2027,6 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { } void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { - D->setExplicitSpecifier(Record.readExplicitSpec()); VisitCXXMethodDecl(D); } @@ -3752,7 +3750,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { 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); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ca61edd..756411a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1266,6 +1266,7 @@ void ASTWriter::WriteBlockInfoBlock() { 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); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 5c0f2df..159a76d 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -535,6 +535,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(static_cast(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()); @@ -637,18 +638,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Code = serialization::DECL_FUNCTION; } -static void addExplicitSpecifier(ExplicitSpecifier ES, - ASTRecordWriter &Record) { - uint64_t Kind = static_cast(ES.getKind()); - Kind = Kind << 1 | static_cast(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; @@ -1341,15 +1331,19 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { } 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) { @@ -1363,7 +1357,6 @@ void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { } void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { - addExplicitSpecifier(D->getExplicitSpecifier(), Record); VisitCXXMethodDecl(D); Code = serialization::DECL_CXX_CONVERSION; } @@ -2163,6 +2156,7 @@ void ASTWriter::WriteDeclAbbrevs() { 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 diff --git a/clang/test/CXX/temp/temp.deduct.guide/p1.cpp b/clang/test/CXX/temp/temp.deduct.guide/p1.cpp index 86aa29d..8bb9da8 100644 --- a/clang/test/CXX/temp/temp.deduct.guide/p1.cpp +++ b/clang/test/CXX/temp/temp.deduct.guide/p1.cpp @@ -71,7 +71,7 @@ extern A(int(&)[26]) -> A; #endif mutable A(int(&)[27]) -> A; // expected-error-re {{{{'mutable' cannot be applied to|illegal storage class on}} function}} virtual A(int(&)[28]) -> A; // expected-error {{'virtual' can only appear on non-static member functions}} -const A(int(&)[31]) -> A; // expected-error {{deduction guide cannot be declared 'const'}} +const A(int(&)[28]) -> A; // expected-error {{deduction guide cannot be declared 'const'}} const volatile static constexpr inline A(int(&)[29]) -> A; // expected-error {{deduction guide cannot be declared 'static inline constexpr const volatile'}} diff --git a/clang/test/CXX/temp/temp.deduct.guide/p3.cpp b/clang/test/CXX/temp/temp.deduct.guide/p3.cpp index ec39c0c..07d1be0 100644 --- a/clang/test/CXX/temp/temp.deduct.guide/p3.cpp +++ b/clang/test/CXX/temp/temp.deduct.guide/p3.cpp @@ -3,14 +3,14 @@ // The same restrictions apply to the parameter-declaration-clause of a // deduction guide as in a function declaration. template struct A {}; -A(void) -> A; // expected-note {{previous}} +A(void) -> A; // ok A(void, int) -> A; // expected-error {{'void' must be the first and only parameter if specified}} -A() -> A; // 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; // ok, redeclaration A() -> A; // expected-note {{previous}} -// expected-error@-1 {{redeclaration of deduction guide}} A() -> A; // FIXME: "functions" is a poor term. expected-error {{functions that differ only in their return type cannot be overloaded}} template A(T) -> A; diff --git a/clang/test/PCH/cxx-explicit-specifier.cpp b/clang/test/PCH/cxx-explicit-specifier.cpp deleted file mode 100644 index a800cfc..0000000 --- a/clang/test/PCH/cxx-explicit-specifier.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// 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 struct T { - template - explicit((Y{}, true)) T(A &&a) {} - }; - - template struct U : T { - using T::T; - }; - - U foo(char ch) { - return U(ch); - } -} -#else -namespace inheriting_constructor { -U 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 -struct B { - static constexpr bool value = b; -}; - -template -struct A { - explicit(b) A(B) {} - template - explicit(b ^ T::value) operator T(); -}; -B b_true; -B 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 b = a_true; -B b1 = a_false; //expected-error {{no viable conversion}} -B b2(a_true); - -#endif - -} - -namespace guide { - -#ifndef USE_PCH - -template -struct A { - A(T); -}; - -template -explicit(true) A(T) -> A; - -explicit(false) A(int) -> A; - -#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 - -} diff --git a/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp b/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp index b2ec5cb..47b54d6 100644 --- a/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp +++ b/clang/test/SemaCXX/builtin-is-constant-evaluated.cpp @@ -115,7 +115,7 @@ static_assert(&r == &x); #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 diff --git a/clang/test/SemaCXX/cxx2a-compat.cpp b/clang/test/SemaCXX/cxx2a-compat.cpp index 49db0bc..d51f1e6 100644 --- a/clang/test/SemaCXX/cxx2a-compat.cpp +++ b/clang/test/SemaCXX/cxx2a-compat.cpp @@ -37,23 +37,3 @@ string u8str = u8"test" u8"test"; // 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 -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 diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp deleted file mode 100644 index 1c532cf..0000000 --- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ /dev/null @@ -1,719 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify - -template struct enable_ifv {}; - -template struct enable_ifv { - static constexpr auto value = val; -}; - -template struct is_same { - static constexpr bool value = false; -}; - -template struct is_same { - static constexpr bool value = true; -}; - -namespace special_cases -{ - -template -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 -struct B { - explicit(b) - // expected-error@-1 {{use of undeclared identifier}} - B(int); -}; - -template -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 - 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 struct E { - // expected-note@-1+ {{candidate constructor}} - explicit((T{}, false)) - // expected-error@-1 {{illegal initializer type 'void'}} - E(int); -}; - -E e = 1; -// expected-error@-1 {{no viable conversion}} -// expected-note@-2 {{in instantiation of}} - -} - -namespace trailling_object { - -template -struct B { - explicit(b) B(int) {} -}; - -template -struct A : B { - explicit(b) A(int) : B(0) {} -}; - -A a(0); - -} - -namespace constructor1 { - -template - 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 -A::A(int, int) {} - -void f() -{ -A a0 = 0; // expected-error {{no viable conversion}} -A a1( 0); -A && a2 = 0;// expected-error {{could not bind}} -A && a3( 0);// expected-error {{could not bind}} -A a4{ 0}; -A && a5 = { 0};// expected-error {{chosen constructor is explicit}} -A && a6{ 0}; -A a7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} - -a0 = 0; -a1 = { 0}; // expected-error {{no viable overloaded '='}} -a2 = A( 0); -a3 = A{ 0}; - -A c0 = ((short)0); -A c1( ((short)0)); -A && c2 = ((short)0); -A && c3( ((short)0)); -A c4{ ((short)0)}; -A && c5 = { ((short)0)}; -A && c6{ ((short)0)}; - -A d1( 0, 0); -A d2{ 0, 0}; -A d3 = { 0, 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} - -d1 = { 0, 0}; // expected-error {{no viable overloaded '='}} -d2 = A( 0, 0); -d3 = A{ 0, 0}; -} -} - -namespace constructor2 { - -template -struct A { - // expected-note@-1 {{candidate constructor}} expected-note@-1 {{candidate constructor}} - // expected-note@-2 {{candidate constructor}} expected-note@-2 {{candidate constructor}} - template - explicit(a ^ is_same::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 a0 = 0.0; // expected-error {{no viable conversion}} -A a1( 0.0); -A && a2 = 0.0;// expected-error {{could not bind}} -A && a3( 0.0);// expected-error {{could not bind}} -A a4{ 0.0}; -A && a5 = { 0.0};// expected-error {{chosen constructor is explicit}} -A && a6{ 0.0}; -A a7 = { 0.0}; // expected-error {{chosen constructor is explicit in copy-initialization}} - -A b0 = 0; -A b1( 0); -A && b2 = 0; -A && b3( 0); -A b4{ 0}; -A && b5 = { 0}; -A && b6{ 0}; -A b7 = { 0}; - -A c0 = 0; // expected-error {{no viable conversion}} -A c1( 0); -A && c2 = 0;// expected-error {{could not bind}} -A && c3( 0);// expected-error {{could not bind}} -A c4{ 0}; -A && c5 = { 0};// expected-error {{chosen constructor is explicit}} -A && c6{ 0}; -A c7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} - -} - -namespace constructor_sfinae { - -template -struct A { - // expected-note@-1+ {{candidate constructor}} - template - explicit(enable_ifv::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 - explicit(enable_ifv::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 a0 = 0.0; // expected-error {{no viable conversion}} -A a1( 0.0); // expected-error {{no matching constructor}} -A a4{ 0.0}; // expected-error {{no matching constructor}} -A a7 = { 0.0}; // expected-error {{no matching constructor}} - -A b0 = 0; // expected-error {{no viable conversion}} -A b1( 0); -A b4{ 0}; -A b7 = { 0}; // expected-error {{chosen constructor is explicit}} - -A c0 = 0; -A c1( 0); -A c4{ 0}; -A c7 = { 0}; - -A d0 = true; // expected-error {{no viable conversion}} -A d1( true); -A d4{ true}; -A d7 = { true}; // expected-error {{chosen constructor is explicit}} - -} - -namespace conversion { - -template -struct A { - explicit(a) operator int (); -}; - -template -A::operator int() { - return 0; -} - -A A_true; -A A_false; - -int ai0 = A(); // expected-error {{no viable conversion}} -const int& ai1 = A(); // expected-error {{no viable conversion}} -int&& ai3 = A(); // 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()}; // expected-error {{no viable conversion}} -const int& ai11 = {A()}; // expected-error {{no viable conversion}} -int&& ai31 = {A()}; // 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()); -const int& ae1(A()); -int&& ae3(A()); -int ae4(A_true); -const int& ae5(A_true); - -int bi0 = A(); -const int& bi1 = A(); -int&& bi3 = A(); -int bi4 = A_false; -const int& bi5 = A_false; - -int bi01 = {A()}; -const int& bi11 = {A()}; -int&& bi31 = {A()}; -int bi41 = {A_false}; -const int& bi51 = {A_false}; - -int be0(A()); -const int& be1(A()); -int&& be3(A()); -int be4(A_true); -const int& be5(A_true); - -} - -namespace conversion2 { - -struct B {}; -// expected-note@-1+ {{candidate constructor}} -template -struct A { - template - explicit(enable_ifv::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 A_false; -A A_true; - -int ai0 = A(); // expected-error {{no viable conversion}} -const int& ai1 = A(); // expected-error {{no viable conversion}} -int&& ai3 = A(); // 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()}; // expected-error {{no viable conversion}} -const int& ae1{A()}; // expected-error {{no viable conversion}} -int&& ae3{A()}; // 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())); // expected-error {{no viable conversion}} -const int& ap1((A())); // expected-error {{no viable conversion}} -int&& ap3((A())); // 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(); // expected-error {{no viable conversion}} -const B & b1 = A(); // expected-error {{no viable conversion}} -B && b3 = A(); // 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()); -const B& be1(A()); -B&& be3(A()); -B be4(A_true); -const B& be5(A_true); - -B c0 = A(); -const B & c1 = A(); -B && c3 = A(); -B c4 = A_false; -const B & c5 = A_false; - -} - -namespace parameter_pack { - -template -struct A { - // expected-note@-1+ {{candidate constructor}} - // expected-note@-2+ {{candidate function}} - template - explicit((is_same::value && ...)) - // expected-note@-1 {{explicit(bool) specifier resolved to true}} - A(Ts...); - // expected-note@-1 {{candidate constructor}} - // expected-note@-2 {{explicit constructor}} -}; - -template -template -A::A(Ts ...) {} - -void f() { - -A a0 = 0; // expected-error {{no viable conversion}} -A a1( 0, 1); -A a2{ 0, 1}; -A 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 b0 = 0; -A b1( 0, 1); -A b2{ 0, 1}; -A b3 = { 0, 1}; - -b1 = 0; -b2 = { 0, 1}; - -} - -} - -namespace deduction_guide { - -template -struct B {}; - -B b_true; -B b_false; - -template -struct nondeduced -{ -using type = T; -}; - -template -struct A { - // expected-note@-1+ {{candidate function}} - explicit(false) - A(typename nondeduced::type, typename nondeduced::type, typename nondeduced>::type) {} - // expected-note@-1+ {{candidate template ignored}} -}; - -template -explicit(enable_ifv::value, b>::value) -A(T1, T2, B) -> A; -// 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 -struct A { - //expected-note@-1+ {{candidate function}} - template - explicit(b) - A(T1, T2) {} - //expected-note@-1 {{explicit constructor declared here}} -}; - -template -explicit(!is_same::value) -A(T1, T2) -> A::value>; -// expected-note@-1+ {{explicit deduction guide declared here}} - -template -A 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()); -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()); -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 -struct A { - explicit(!b) operator int(); - explicit(b) operator bool(); -}; - -template -A::operator bool() { return false; } - -struct B { - void f(int); - void f(bool); -}; - -void f(A a, B b) { - b.f(a); -} - -void f1(A a, B b) { - b.f(a); -} - -// Taken from 12.3.2p2 -class X { X(); }; -class Y { }; // expected-note+ {{candidate constructor (the implicit}} - -template -struct Z { - explicit(b) operator X() const; - explicit(b) operator Y() const; - explicit(b) operator int() const; -}; - -void testExplicit() -{ -Z 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(z); -// 13.3.1.5p1 & 8.5p16: -int i1 = (int)z; -int i2 = int(z); -int i3 = static_cast(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 -struct C { - template - explicit(!is_same::value) - // expected-note@-1+ {{explicit(bool) specifier resolved to true}} - operator T(); - // expected-note@-1+ {{candidate conversion operator ignored}} -}; - -using Bool = C; -using Integral = C; -using Unrelated = C; - -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 -struct A { - // expected-note@-1+ {{candidate template ignored}} - explicit(!is_same::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 -explicit A(T1, T2) -> A; -// 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}} - -} diff --git a/clang/test/SemaCXX/explicit.cpp b/clang/test/SemaCXX/explicit.cpp index bd1199f..a3902e5 100644 --- a/clang/test/SemaCXX/explicit.cpp +++ b/clang/test/SemaCXX/explicit.cpp @@ -1,6 +1,4 @@ // 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); @@ -185,8 +183,7 @@ namespace Conversion { const int ©List7 = {b}; const int ©List8 = {n}; // expected-error {{no viable conversion}} } - -#if __cplusplus < 201707L + void testNew() { // 5.3.4p6: @@ -203,8 +200,7 @@ namespace Conversion { 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: diff --git a/clang/unittests/AST/Language.cpp b/clang/unittests/AST/Language.cpp index 68b78a31..210014b 100644 --- a/clang/unittests/AST/Language.cpp +++ b/clang/unittests/AST/Language.cpp @@ -34,9 +34,6 @@ ArgVector getBasicRunOptionsForLanguage(Language Lang) { 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!"); diff --git a/clang/unittests/AST/Language.h b/clang/unittests/AST/Language.h index dd61ef8..cd19fb7 100644 --- a/clang/unittests/AST/Language.h +++ b/clang/unittests/AST/Language.h @@ -28,7 +28,6 @@ enum Language { Lang_CXX, Lang_CXX11, Lang_CXX14, - Lang_CXX2a, Lang_OpenCL, Lang_OBJCXX }; diff --git a/clang/unittests/AST/MatchVerifier.h b/clang/unittests/AST/MatchVerifier.h index 7aca7f4..1d1bf57 100644 --- a/clang/unittests/AST/MatchVerifier.h +++ b/clang/unittests/AST/MatchVerifier.h @@ -108,10 +108,6 @@ testing::AssertionResult MatchVerifier::match( 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; diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 5bb4f7e..211b953 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -806,26 +806,6 @@ TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { 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().match( - get<0>(Decls), cxxConstructorDecl(hasName("foo"))); - CXXConstructorDecl *Second = FirstDeclMatcher().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().match( - get<0>(Decls), cxxConstructorDecl(hasName("foo"))); - CXXConstructorDecl *Second = FirstDeclMatcher().match( - get<1>(Decls), cxxConstructorDecl(hasName("foo"))); - EXPECT_TRUE(testStructuralMatch(First, Second)); -} - struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {}; TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) { @@ -873,25 +853,5 @@ TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) { EXPECT_FALSE(testStructuralMatch(t)); } -TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) { - auto Decls = makeNamedDecls("template struct foo {explicit(b) foo(int);};", - "template struct foo {explicit(b) foo(int);};", Lang_CXX2a); - CXXConstructorDecl *First = FirstDeclMatcher().match( - get<0>(Decls), cxxConstructorDecl(hasName("foo"))); - CXXConstructorDecl *Second = FirstDeclMatcher().match( - get<1>(Decls), cxxConstructorDecl(hasName("foo"))); - EXPECT_TRUE(testStructuralMatch(First, Second)); -} - -TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) { - auto Decls = makeNamedDecls("template struct foo {explicit(b) foo(int);};", - "template struct foo {explicit(!b) foo(int);};", Lang_CXX2a); - CXXConstructorDecl *First = FirstDeclMatcher().match( - get<0>(Decls), cxxConstructorDecl(hasName("foo"))); - CXXConstructorDecl *Second = FirstDeclMatcher().match( - get<1>(Decls), cxxConstructorDecl(hasName("foo"))); - EXPECT_FALSE(testStructuralMatch(First, Second)); -} - } // end namespace ast_matchers } // end namespace clang diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 7d17f7a..dd6399d 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1002,7 +1002,7 @@ as the draft C++2a standard evolves. explicit(bool) P0892R2 - SVN + No diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 252dcfc..22c9a70 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -8167,10 +8167,6 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( 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(), @@ -8189,7 +8185,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( 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; @@ -8224,7 +8220,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( clang::SourceLocation()), method_qual_type, nullptr, // TypeSourceInfo * - is_inline, explicit_spec, false /*is_constexpr*/, + is_inline, is_explicit, false /*is_constexpr*/, clang::SourceLocation()); } } -- 2.7.4