summaryrefslogtreecommitdiffstats
path: root/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTImporter.cpp28
-rw-r--r--lib/AST/ASTStructuralEquivalence.cpp6
-rw-r--r--lib/AST/Decl.cpp1
-rw-r--r--lib/AST/DeclCXX.cpp109
-rw-r--r--lib/AST/DeclPrinter.cpp22
5 files changed, 115 insertions, 51 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 300c3c9ada..004c466c8d 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -3047,11 +3047,20 @@ 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,
- FromConstructor->isExplicit(),
- D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ ToInnerLocStart, NameInfo, T, TInfo,
+ ExplicitSpecifier(
+ ExplicitExpr,
+ FromConstructor->getExplicitSpecifier().getKind()),
+ D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
return ToFunction;
} else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {
@@ -3077,10 +3086,19 @@ 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(),
- FromConversion->isExplicit(), D->isConstexpr(), SourceLocation()))
+ ExplicitSpecifier(ExplicitExpr,
+ FromConversion->getExplicitSpecifier().getKind()),
+ D->isConstexpr(), SourceLocation()))
return ToFunction;
} else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (GetImportedOrCreateDecl<CXXMethodDecl>(
diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp
index 71bbd82481..f3c34d73bd 100644
--- a/lib/AST/ASTStructuralEquivalence.cpp
+++ b/lib/AST/ASTStructuralEquivalence.cpp
@@ -955,13 +955,15 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
- if (Constructor1->isExplicit() != Constructor2->isExplicit())
+ if (!Constructor1->getExplicitSpecifier().isEquivalent(
+ Constructor2->getExplicitSpecifier()))
return false;
}
if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
auto *Conversion2 = cast<CXXConversionDecl>(Method2);
- if (Conversion1->isExplicit() != Conversion2->isExplicit())
+ if (!Conversion1->getExplicitSpecifier().isEquivalent(
+ Conversion2->getExplicitSpecifier()))
return false;
if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(),
Conversion2->getConversionType()))
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 19fd3882bd..499a451380 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2713,7 +2713,6 @@ 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/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 4bd5ee1bb6..9946d16a85 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1862,19 +1862,47 @@ 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, bool IsExplicit,
- const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- SourceLocation EndLocation) {
- return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, IsExplicit,
- NameInfo, T, TInfo, EndLocation);
+ 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);
}
CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) CXXDeductionGuideDecl(C, nullptr, SourceLocation(), false,
- DeclarationNameInfo(), QualType(),
- nullptr, SourceLocation());
+ return new (C, ID) CXXDeductionGuideDecl(
+ C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
+ QualType(), nullptr, SourceLocation());
}
void CXXMethodDecl::anchor() {}
@@ -2312,47 +2340,54 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
CXXConstructorDecl::CXXConstructorDecl(
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
- bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared,
+ ExplicitSpecifier ES, 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;
- setExplicitSpecified(isExplicitSpecified);
+ setExplicitSpecifier(ES);
}
void CXXConstructorDecl::anchor() {}
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
- bool Inherited) {
- unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(Inherited);
+ uint64_t AllocKind) {
+ bool hasTraillingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit);
+ bool isInheritingConstructor =
+ static_cast<bool>(AllocKind & TAKInheritsConstructor);
+ unsigned Extra =
+ additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
+ isInheritingConstructor, hasTraillingExplicit);
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
- false, false, false, false, InheritedConstructor());
- Result->setInheritingConstructor(Inherited);
+ ExplicitSpecifier(), false, false, false, InheritedConstructor());
+ Result->setInheritingConstructor(isInheritingConstructor);
+ Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
+ hasTraillingExplicit;
+ Result->setExplicitSpecifier(ExplicitSpecifier());
return Result;
}
-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) {
+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) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
unsigned Extra =
- additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0);
- return new (C, RD, Extra) CXXConstructorDecl(
- C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline,
- isImplicitlyDeclared, isConstexpr, Inherited);
+ 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);
}
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
@@ -2503,25 +2538,21 @@ void CXXConversionDecl::anchor() {}
CXXConversionDecl *
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXConversionDecl(C, nullptr, SourceLocation(),
- DeclarationNameInfo(), QualType(),
- nullptr, false, false, false,
- SourceLocation());
+ return new (C, ID) CXXConversionDecl(
+ C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
+ false, ExplicitSpecifier(), false, SourceLocation());
}
-CXXConversionDecl *
-CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- bool isInline, bool isExplicit,
- bool isConstexpr, SourceLocation EndLocation) {
+CXXConversionDecl *CXXConversionDecl::Create(
+ ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
+ bool isInline, ExplicitSpecifier ES, 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, isExplicit, isConstexpr,
- EndLocation);
+ isInline, ES, isConstexpr, EndLocation);
}
bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index c98ec3b85d..36c5d10f71 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -552,6 +552,21 @@ 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())
@@ -582,10 +597,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->isVirtualAsWritten()) Out << "virtual ";
if (D->isModulePrivate()) Out << "__module_private__ ";
if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
- if ((CDecl && CDecl->isExplicitSpecified()) ||
- (ConversionDecl && ConversionDecl->isExplicitSpecified()) ||
- (GuideDecl && GuideDecl->isExplicitSpecified()))
- Out << "explicit ";
+ ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);
+ if (ExplicitSpec.isSpecified())
+ printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation);
}
PrintingPolicy SubPolicy(Policy);