diff options
author | Hans Wennborg <hans@hanshq.net> | 2019-05-06 09:51:10 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2019-05-06 09:51:10 +0000 |
commit | d2b9fc88c8c4c758068da680cd0e42e6ca41ffcd (patch) | |
tree | a211c3ae7ae48386887be271a497d37fbb8088bc /clang/lib | |
parent | 3cfb48b87729a656128a2f4c9884f66f7eccb353 (diff) | |
download | bcm5719-llvm-d2b9fc88c8c4c758068da680cd0e42e6ca41ffcd.tar.gz bcm5719-llvm-d2b9fc88c8c4c758068da680cd0e42e6ca41ffcd.zip |
Revert r359949 "[clang] adding explicit(bool) from c++2a"
This caused Clang to start erroring on the following:
struct S {
template <typename = int> 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<Expr*, 2> 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
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 28 | ||||
-rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 109 | ||||
-rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Frontend/InitPreprocessor.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 62 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 59 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 88 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 173 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 53 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 24 |
20 files changed, 240 insertions, 478 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 1ab99bec38b..1ac4870cabe 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<CXXConstructorDecl>(D)) { - Expr *ExplicitExpr = nullptr; - if (FromConstructor->getExplicitSpecifier().getExpr()) { - auto Imp = importSeq(FromConstructor->getExplicitSpecifier().getExpr()); - if (!Imp) - return Imp.takeError(); - std::tie(ExplicitExpr) = *Imp; - } if (GetImportedOrCreateDecl<CXXConstructorDecl>( - ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - ToInnerLocStart, NameInfo, T, TInfo, - ExplicitSpecifier( - ExplicitExpr, - FromConstructor->getExplicitSpecifier().getKind()), - D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, + FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) { @@ -3094,19 +3085,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast<CXXConversionDecl>(D)) { - Expr *ExplicitExpr = nullptr; - if (FromConversion->getExplicitSpecifier().getExpr()) { - auto Imp = importSeq(FromConversion->getExplicitSpecifier().getExpr()); - if (!Imp) - return Imp.takeError(); - std::tie(ExplicitExpr) = *Imp; - } if (GetImportedOrCreateDecl<CXXConversionDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), - ExplicitSpecifier(ExplicitExpr, - FromConversion->getExplicitSpecifier().getKind()), - D->isConstexpr(), SourceLocation())) + FromConversion->isExplicit(), D->isConstexpr(), SourceLocation())) return ToFunction; } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { if (GetImportedOrCreateDecl<CXXMethodDecl>( diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index f3c34d73bdb..71bbd824812 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<CXXConstructorDecl>(Method1)) { auto *Constructor2 = cast<CXXConstructorDecl>(Method2); - if (!Constructor1->getExplicitSpecifier().isEquivalent( - Constructor2->getExplicitSpecifier())) + if (Constructor1->isExplicit() != Constructor2->isExplicit()) return false; } if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) { auto *Conversion2 = cast<CXXConversionDecl>(Method2); - if (!Conversion1->getExplicitSpecifier().isEquivalent( - Conversion2->getExplicitSpecifier())) + if (Conversion1->isExplicit() != Conversion2->isExplicit()) return false; if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(), Conversion2->getConversionType())) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 499a4513804..19fd3882bd4 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 b9ecdc65720..d7eae5ad1e1 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<CXXConstructorDecl>(Function)->getExplicitSpecifier(); - case Decl::Kind::CXXConversion: - return cast<CXXConversionDecl>(Function)->getExplicitSpecifier(); - case Decl::Kind::CXXDeductionGuide: - return cast<CXXDeductionGuideDecl>(Function)->getExplicitSpecifier(); - default: - return {}; - } -} - CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( - ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, SourceLocation EndLocation) { - return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, - TInfo, EndLocation); + ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + SourceLocation EndLocation) { + return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, IsExplicit, + NameInfo, T, TInfo, EndLocation); } CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) CXXDeductionGuideDecl( - C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), - QualType(), nullptr, SourceLocation()); + return new (C, ID) CXXDeductionGuideDecl(C, nullptr, SourceLocation(), false, + DeclarationNameInfo(), QualType(), + nullptr, SourceLocation()); } void CXXMethodDecl::anchor() {} @@ -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<bool>(Inherited)); setImplicit(isImplicitlyDeclared); - CXXConstructorDeclBits.HasTrailingExplicitSpecifier = ES.getExpr() ? 1 : 0; if (Inherited) *getTrailingObjects<InheritedConstructor>() = Inherited; - setExplicitSpecifier(ES); + setExplicitSpecified(isExplicitSpecified); } void CXXConstructorDecl::anchor() {} CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID, - uint64_t AllocKind) { - bool hasTraillingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit); - bool isInheritingConstructor = - static_cast<bool>(AllocKind & TAKInheritsConstructor); - unsigned Extra = - additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>( - isInheritingConstructor, hasTraillingExplicit); + bool Inherited) { + unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(Inherited); auto *Result = new (C, ID, Extra) CXXConstructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - ExplicitSpecifier(), false, false, false, InheritedConstructor()); - Result->setInheritingConstructor(isInheritingConstructor); - Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = - hasTraillingExplicit; - Result->setExplicitSpecifier(ExplicitSpecifier()); + false, false, false, false, InheritedConstructor()); + Result->setInheritingConstructor(Inherited); return Result; } -CXXConstructorDecl *CXXConstructorDecl::Create( - ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - bool isConstexpr, InheritedConstructor Inherited) { +CXXConstructorDecl * +CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + bool isExplicit, bool isInline, + bool isImplicitlyDeclared, bool isConstexpr, + InheritedConstructor Inherited) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); unsigned Extra = - additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>( - Inherited ? 1 : 0, ES.getExpr() ? 1 : 0); - return new (C, RD, Extra) - CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline, - isImplicitlyDeclared, isConstexpr, Inherited); + additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0); + return new (C, RD, Extra) CXXConstructorDecl( + C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline, + isImplicitlyDeclared, isConstexpr, Inherited); } CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { @@ -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 78a7afdbf09..325400e4630 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 5aa2ea3fba1..b0fb124251e 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 f883ecc45f1..c4f02b9b999 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 <atomic>. @@ -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<Expr *>(nullptr)); - BalancedDelimiterTracker Tracker(*this, tok::l_paren); - Tracker.consumeOpen(); - ExplicitExpr = ParseConstantExpression(); - RangeEnd = Tok.getLocation(); - if (ExplicitExpr.isUsable()) { - CloseParenLoc = Tok.getLocation(); - Tracker.consumeClose(); - ExplicitSpec = - Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get()); - } else - Tracker.skipToEnd(); - } else - Diag(Tok.getLocation(), diag::warn_cxx2a_compat_explicit_bool); - } - isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID, - ExplicitSpec, CloseParenLoc); + case tok::kw_explicit: + isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID); break; - } case tok::kw__Noreturn: if (!getLangOpts().C11) Diag(Loc, diag::ext_c11_noreturn); @@ -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 df2792289e4..4f3e2faa8e0 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 d86668c49fb..c2d80409f1a 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<FunctionTemplateDecl>(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 86b5645d115..379e2aefb46 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<CXXRecordDecl>(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<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, isInline, ExplicitSpecifier, isConstexpr, SourceLocation()); + TInfo, isInline, isExplicit, isConstexpr, SourceLocation()); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { SemaRef.CheckDeductionGuideDeclarator(D, R, SC); return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), - ExplicitSpecifier, NameInfo, R, TInfo, + isExplicit, NameInfo, R, TInfo, D.getEndLoc()); } else if (DC->isRecord()) { // If the name of the function is the same as the name of the record, @@ -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<CXXDeductionGuideDecl>(NewFD)) { if (!CurContext->isRecord()) { // 'explicit' was specified outside of the class. Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_out_of_class) - << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecRange()); + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); } else if (!isa<CXXConstructorDecl>(NewFD) && !isa<CXXConversionDecl>(NewFD)) { // 'explicit' was specified on a function that wasn't a constructor // or conversion function. Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_non_ctor_or_conv_function) - << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecRange()); + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8ddc5f12cf1..7e4aab0fae5 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<CXXDeductionGuideDecl>(New) && - !New->isFunctionTemplateSpecialization()) { - Diag(New->getLocation(), diag::err_deduction_guide_redeclared); + // FIXME: It's not clear what should happen if multiple declarations of a + // deduction guide have different explicitness. For now at least we simply + // reject any case where the explicitness changes. + auto *NewGuide = dyn_cast<CXXDeductionGuideDecl>(New); + if (NewGuide && NewGuide->isExplicitSpecified() != + cast<CXXDeductionGuideDecl>(Old)->isExplicitSpecified()) { + Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch) + << NewGuide->isExplicitSpecified(); Diag(Old->getLocation(), diag::note_previous_declaration); } @@ -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 5b78d449d0c..e8a8887736e 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<CXXConversionDecl>(D); - if (AllowExplicit || !Conv->isExplicit()) { + if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate( - ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, - CandidateSet, AllowExplicit, AllowExplicit, - /*AllowResultConversion*/ false); + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), + ActingDC, Initializer, DestType, + CandidateSet, AllowExplicit, + /*AllowResultConversion*/false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit, - AllowExplicit, - /*AllowResultConversion*/ false); + /*AllowResultConversion*/false); } } } @@ -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 1966e9e0803..b686681f04f 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 a91c20e00a6..2b7924d244e 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<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1ef932e05e9..df979b68b6e 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<Expr *> Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, - bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, - ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions) { +void Sema::AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions, + bool PartialOverloading, bool AllowExplicit, + ADLCallKind IsADLCandidate, + ConversionSequenceList EarlyConversions) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -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<Expr *> 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<CXXConversionDecl>(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<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, Args, - CandidateSet, - /*SupressUserConversions=*/false, PartialOverloading, - /*AllowExplicit*/ false, ADLCallKind::UsesADL); + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, + ExplicitTemplateArgs, Args, CandidateSet, + /*SupressUserConversions=*/false, + PartialOverloading, ADLCallKind::UsesADL); } } } @@ -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<CXXConstructorDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "constructor"; - break; - case Decl::Kind::CXXConversion: - ES = cast<CXXConversionDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "conversion operator"; - break; - case Decl::Kind::CXXDeductionGuide: - ES = cast<CXXDeductionGuideDecl>(Cand->Function)->getExplicitSpecifier(); - DeclName = "deductiong guide"; - break; - default: - llvm_unreachable("invalid Decl"); - } - assert(ES.getExpr() && "null expression should be handled before"); - S.Diag(Cand->Function->getLocation(), - diag::note_ovl_candidate_explicit_forbidden) - << DeclName; - S.Diag(ES.getExpr()->getBeginLoc(), - diag::note_explicit_bool_resolved_to_true); -} - static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Callee = Cand->Function; @@ -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<CXXConstructorDecl>(Func)) { - AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, - CandidateSet, - /*SuppressUserConversions*/ false, - /*PartialOverloading*/ false, - /*AllowExplicit*/ true); + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), + Args, CandidateSet); } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b2f80ebd119..58ad439747e 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 1c7341d3cf8..653eb693268 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<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); - ExplicitSpecifier InstantiatedExplicitSpecifier; - if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { - InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( - SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; - } - SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -1758,9 +1727,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionDecl *Function; if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { Function = CXXDeductionGuideDecl::Create( - SemaRef.Context, DC, D->getInnerLocStart(), - InstantiatedExplicitSpecifier, NameInfo, T, TInfo, - D->getSourceRange().getEnd()); + SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(), + NameInfo, T, TInfo, D->getSourceRange().getEnd()); if (DGuide->isCopyDeductionCandidate()) cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate(); Function->setAccess(D->getAccess()); @@ -2028,12 +1996,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } } - ExplicitSpecifier InstantiatedExplicitSpecifier = - instantiateExplicitSpecifier(SemaRef, TemplateArgs, - ExplicitSpecifier::getFromDecl(D), D); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; - SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -2073,10 +2035,11 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - Method = CXXConstructorDecl::Create( - SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, - Constructor->isConstexpr()); + Method = CXXConstructorDecl::Create(SemaRef.Context, Record, + StartLoc, NameInfo, T, TInfo, + Constructor->isExplicit(), + Constructor->isInlineSpecified(), + false, Constructor->isConstexpr()); Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, @@ -2087,7 +2050,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, + Conversion->isInlineSpecified(), Conversion->isExplicit(), Conversion->isConstexpr(), Conversion->getEndLoc()); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 27fcc9e40b5..ffe0e8bd74e 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<StorageClass>(Record.readInt())); FD->setInlineSpecified(Record.readInt()); FD->setImplicitlyInline(Record.readInt()); + FD->setExplicitSpecified(Record.readInt()); FD->setVirtualAsWritten(Record.readInt()); FD->setPure(Record.readInt()); FD->setHasInheritedPrototype(Record.readInt()); @@ -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<ConstructorUsingShadowDecl>(); auto *Ctor = ReadDeclAs<CXXConstructorDecl>(); @@ -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 ca61edd8d29..756411a8c5b 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 5c0f2dff56e..159a76d5efb 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<int>(D->getStorageClass())); // FIXME: stable encoding Record.push_back(D->isInlineSpecified()); Record.push_back(D->isInlined()); + Record.push_back(D->isExplicitSpecified()); Record.push_back(D->isVirtualAsWritten()); Record.push_back(D->isPure()); Record.push_back(D->hasInheritedPrototype()); @@ -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<uint64_t>(ES.getKind()); - Kind = Kind << 1 | static_cast<bool>(ES.getExpr()); - Record.push_back(Kind); - if (ES.getExpr()) { - Record.AddStmt(ES.getExpr()); - } -} - void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { - addExplicitSpecifier(D->getExplicitSpecifier(), Record); VisitFunctionDecl(D); Record.push_back(D->isCopyDeductionCandidate()); Code = serialization::DECL_CXX_DEDUCTION_GUIDE; @@ -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 |