Skip to content

Commit a57aaed

Browse files
Ast importer visitors (#138838)
I've rebased commit from [Evianaive](https://github.com/Evianaive/llvm-project/commits?author=Evianaive) and compiled it. I hope it will speed up fix for #129393. --------- Co-authored-by: Evianaive <153540933@qq.com>
1 parent fcecf17 commit a57aaed

File tree

7 files changed

+419
-0
lines changed

7 files changed

+419
-0
lines changed

clang/include/clang/AST/ExprConcepts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ class ExprRequirement : public Requirement {
310310
// TODO: Can we maybe not save the whole template parameter list and just
311311
// the type constraint? Saving the whole TPL makes it easier to handle in
312312
// serialization but is less elegant.
313+
ReturnTypeRequirement(TemplateParameterList *TPL, bool IsDependent);
313314
ReturnTypeRequirement(TemplateParameterList *TPL);
314315

315316
bool isDependent() const {

clang/include/clang/ASTMatchers/ASTMatchers.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "clang/AST/DeclTemplate.h"
5656
#include "clang/AST/Expr.h"
5757
#include "clang/AST/ExprCXX.h"
58+
#include "clang/AST/ExprConcepts.h"
5859
#include "clang/AST/ExprObjC.h"
5960
#include "clang/AST/LambdaCapture.h"
6061
#include "clang/AST/NestedNameSpecifier.h"
@@ -1363,6 +1364,26 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl>
13631364
extern const internal::VariadicDynCastAllOfMatcher<Decl, ConceptDecl>
13641365
conceptDecl;
13651366

1367+
/// Matches concept requirement.
1368+
///
1369+
/// Example matches 'requires(T p) { *p; }'
1370+
/// \code
1371+
/// template<typename T>
1372+
/// concept dereferencable = requires(T p) { *p; }
1373+
/// \endcode
1374+
extern const internal::VariadicDynCastAllOfMatcher<Expr, RequiresExpr>
1375+
requiresExpr;
1376+
1377+
/// Matches concept requirement body declaration.
1378+
///
1379+
/// Example matches '{ *p; }'
1380+
/// \code
1381+
/// template<typename T>
1382+
/// concept dereferencable = requires(T p) { *p; }
1383+
/// \endcode
1384+
extern const internal::VariadicDynCastAllOfMatcher<Decl, RequiresExprBodyDecl>
1385+
requiresExprBodyDecl;
1386+
13661387
/// Matches variable declarations.
13671388
///
13681389
/// Note: this does not match declarations of member variables, which are

clang/lib/AST/ASTConcept.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement(
156156
TypeConstraintInfo.setInt(Dependent ? true : false);
157157
}
158158

159+
concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement(
160+
TemplateParameterList *TPL, bool IsDependent)
161+
: TypeConstraintInfo(TPL, IsDependent) {}
162+
159163
concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T)
160164
: Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
161165
T->getType()->containsUnexpandedParameterPack(),

clang/lib/AST/ASTImporter.cpp

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,17 @@ namespace clang {
495495
Expected<InheritedConstructor>
496496
ImportInheritedConstructor(const InheritedConstructor &From);
497497

498+
// Use for allocating string for newly imported object.
499+
StringRef ImportASTStringRef(StringRef FromStr);
500+
Error ImportConstraintSatisfaction(const ASTConstraintSatisfaction &FromSat,
501+
ConstraintSatisfaction &ToSat);
502+
Expected<concepts::Requirement *>
503+
ImportTypeRequirement(concepts::TypeRequirement *From);
504+
Expected<concepts::Requirement *>
505+
ImportExprRequirement(concepts::ExprRequirement *From);
506+
Expected<concepts::Requirement *>
507+
ImportNestedRequirement(concepts::NestedRequirement *From);
508+
498509
template <typename T>
499510
bool hasSameVisibilityContextAndLinkage(T *Found, T *From);
500511

@@ -564,6 +575,9 @@ namespace clang {
564575
ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D);
565576
ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
566577
ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
578+
ExpectedDecl VisitConceptDecl(ConceptDecl* D);
579+
ExpectedDecl VisitRequiresExprBodyDecl(RequiresExprBodyDecl* E);
580+
ExpectedDecl VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl* D);
567581

568582
// Importing statements
569583
ExpectedStmt VisitStmt(Stmt *S);
@@ -680,6 +694,8 @@ namespace clang {
680694
ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
681695
ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
682696
ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E);
697+
ExpectedStmt VisitRequiresExpr(RequiresExpr* E);
698+
ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E);
683699

684700
// Helper for chaining together multiple imports. If an error is detected,
685701
// subsequent imports will return default constructed nodes, so that failure
@@ -1038,6 +1054,177 @@ Expected<ConceptReference *> ASTNodeImporter::import(ConceptReference *From) {
10381054
return ConceptRef;
10391055
}
10401056

1057+
StringRef ASTNodeImporter::ImportASTStringRef(StringRef FromStr) {
1058+
char *ToStore = new (Importer.getToContext()) char[FromStr.size()];
1059+
std::copy(FromStr.begin(), FromStr.end(), ToStore);
1060+
return StringRef(ToStore, FromStr.size());
1061+
}
1062+
1063+
Error ASTNodeImporter::ImportConstraintSatisfaction(
1064+
const ASTConstraintSatisfaction &FromSat, ConstraintSatisfaction &ToSat) {
1065+
ToSat.IsSatisfied = FromSat.IsSatisfied;
1066+
ToSat.ContainsErrors = FromSat.ContainsErrors;
1067+
if (!ToSat.IsSatisfied) {
1068+
for (auto Record = FromSat.begin(); Record != FromSat.end(); ++Record) {
1069+
if (Expr *E = Record->dyn_cast<Expr *>()) {
1070+
ExpectedExpr ToSecondExpr = import(E);
1071+
if (!ToSecondExpr)
1072+
return ToSecondExpr.takeError();
1073+
ToSat.Details.emplace_back(ToSecondExpr.get());
1074+
} else {
1075+
auto Pair = Record->dyn_cast<std::pair<SourceLocation, StringRef> *>();
1076+
1077+
ExpectedSLoc ToPairFirst = import(Pair->first);
1078+
if (!ToPairFirst)
1079+
return ToPairFirst.takeError();
1080+
StringRef ToPairSecond = ImportASTStringRef(Pair->second);
1081+
ToSat.Details.emplace_back(
1082+
new (Importer.getToContext())
1083+
ConstraintSatisfaction::SubstitutionDiagnostic{
1084+
ToPairFirst.get(), ToPairSecond});
1085+
}
1086+
}
1087+
}
1088+
return Error::success();
1089+
}
1090+
1091+
template <>
1092+
Expected<concepts::Requirement::SubstitutionDiagnostic *>
1093+
ASTNodeImporter::import(
1094+
concepts::Requirement::SubstitutionDiagnostic *FromDiag) {
1095+
StringRef ToEntity = ImportASTStringRef(FromDiag->SubstitutedEntity);
1096+
ExpectedSLoc ToLoc = import(FromDiag->DiagLoc);
1097+
if (!ToLoc)
1098+
return ToLoc.takeError();
1099+
StringRef ToDiagMessage = ImportASTStringRef(FromDiag->DiagMessage);
1100+
return new (Importer.getToContext())
1101+
concepts::Requirement::SubstitutionDiagnostic{ToEntity, ToLoc.get(),
1102+
ToDiagMessage};
1103+
}
1104+
1105+
Expected<concepts::Requirement *>
1106+
ASTNodeImporter::ImportTypeRequirement(concepts::TypeRequirement *From) {
1107+
using namespace concepts;
1108+
1109+
if (From->isSubstitutionFailure()) {
1110+
auto DiagOrErr = import(From->getSubstitutionDiagnostic());
1111+
if (!DiagOrErr)
1112+
return DiagOrErr.takeError();
1113+
return new (Importer.getToContext()) TypeRequirement(*DiagOrErr);
1114+
} else {
1115+
Expected<TypeSourceInfo *> ToType = import(From->getType());
1116+
if (!ToType)
1117+
return ToType.takeError();
1118+
return new (Importer.getToContext()) TypeRequirement(*ToType);
1119+
}
1120+
}
1121+
1122+
Expected<concepts::Requirement *>
1123+
ASTNodeImporter::ImportExprRequirement(concepts::ExprRequirement *From) {
1124+
using namespace concepts;
1125+
1126+
bool IsRKSimple = From->getKind() == Requirement::RK_Simple;
1127+
ExprRequirement::SatisfactionStatus Status = From->getSatisfactionStatus();
1128+
1129+
std::optional<ExprRequirement::ReturnTypeRequirement> Req;
1130+
ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
1131+
1132+
if (IsRKSimple) {
1133+
Req.emplace();
1134+
} else {
1135+
const ExprRequirement::ReturnTypeRequirement &FromTypeRequirement =
1136+
From->getReturnTypeRequirement();
1137+
1138+
if (FromTypeRequirement.isTypeConstraint()) {
1139+
const bool IsDependent = FromTypeRequirement.isDependent();
1140+
auto ParamsOrErr =
1141+
import(FromTypeRequirement.getTypeConstraintTemplateParameterList());
1142+
if (!ParamsOrErr)
1143+
return ParamsOrErr.takeError();
1144+
if (Status >= ExprRequirement::SS_ConstraintsNotSatisfied) {
1145+
auto SubstConstraintExprOrErr =
1146+
import(From->getReturnTypeRequirementSubstitutedConstraintExpr());
1147+
if (!SubstConstraintExprOrErr)
1148+
return SubstConstraintExprOrErr.takeError();
1149+
SubstitutedConstraintExpr = SubstConstraintExprOrErr.get();
1150+
}
1151+
Req.emplace(ParamsOrErr.get(), IsDependent);
1152+
} else if (FromTypeRequirement.isSubstitutionFailure()) {
1153+
auto DiagOrErr = import(FromTypeRequirement.getSubstitutionDiagnostic());
1154+
if (!DiagOrErr)
1155+
return DiagOrErr.takeError();
1156+
Req.emplace(DiagOrErr.get());
1157+
} else {
1158+
Req.emplace();
1159+
}
1160+
}
1161+
1162+
ExpectedSLoc NoexceptLocOrErr = import(From->getNoexceptLoc());
1163+
if (!NoexceptLocOrErr)
1164+
return NoexceptLocOrErr.takeError();
1165+
1166+
if (Status == ExprRequirement::SS_ExprSubstitutionFailure) {
1167+
auto DiagOrErr = import(From->getExprSubstitutionDiagnostic());
1168+
if (!DiagOrErr)
1169+
return DiagOrErr.takeError();
1170+
return new (Importer.getToContext()) ExprRequirement(
1171+
*DiagOrErr, IsRKSimple, *NoexceptLocOrErr, std::move(*Req));
1172+
} else {
1173+
Expected<Expr *> ExprOrErr = import(From->getExpr());
1174+
if (!ExprOrErr)
1175+
return ExprOrErr.takeError();
1176+
return new (Importer.getToContext()) concepts::ExprRequirement(
1177+
*ExprOrErr, IsRKSimple, *NoexceptLocOrErr, std::move(*Req), Status,
1178+
SubstitutedConstraintExpr);
1179+
}
1180+
}
1181+
1182+
Expected<concepts::Requirement *>
1183+
ASTNodeImporter::ImportNestedRequirement(concepts::NestedRequirement *From) {
1184+
using namespace concepts;
1185+
1186+
const ASTConstraintSatisfaction &FromSatisfaction =
1187+
From->getConstraintSatisfaction();
1188+
if (From->hasInvalidConstraint()) {
1189+
StringRef ToEntity = ImportASTStringRef(From->getInvalidConstraintEntity());
1190+
ASTConstraintSatisfaction *ToSatisfaction =
1191+
ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),
1192+
FromSatisfaction);
1193+
return new (Importer.getToContext())
1194+
NestedRequirement(ToEntity, ToSatisfaction);
1195+
} else {
1196+
ExpectedExpr ToExpr = import(From->getConstraintExpr());
1197+
if (!ToExpr)
1198+
return ToExpr.takeError();
1199+
if (ToExpr.get()->isInstantiationDependent()) {
1200+
return new (Importer.getToContext()) NestedRequirement(ToExpr.get());
1201+
} else {
1202+
ConstraintSatisfaction Satisfaction;
1203+
if (Error Err =
1204+
ImportConstraintSatisfaction(FromSatisfaction, Satisfaction))
1205+
return std::move(Err);
1206+
return new (Importer.getToContext()) NestedRequirement(
1207+
Importer.getToContext(), ToExpr.get(), Satisfaction);
1208+
}
1209+
}
1210+
}
1211+
1212+
template <>
1213+
Expected<concepts::Requirement *>
1214+
ASTNodeImporter::import(concepts::Requirement *FromRequire) {
1215+
switch (FromRequire->getKind()) {
1216+
case concepts::Requirement::RequirementKind::RK_Type:
1217+
return ImportTypeRequirement(cast<concepts::TypeRequirement>(FromRequire));
1218+
case concepts::Requirement::RequirementKind::RK_Compound:
1219+
case concepts::Requirement::RequirementKind::RK_Simple:
1220+
return ImportExprRequirement(cast<concepts::ExprRequirement>(FromRequire));
1221+
case concepts::Requirement::RequirementKind::RK_Nested:
1222+
return ImportNestedRequirement(
1223+
cast<concepts::NestedRequirement>(FromRequire));
1224+
}
1225+
llvm_unreachable("Unhandled requirement kind");
1226+
}
1227+
10411228
template <>
10421229
Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
10431230
ValueDecl *Var = nullptr;
@@ -6833,6 +7020,62 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
68337020
return ToFunc;
68347021
}
68357022

7023+
ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl *D) {
7024+
DeclContext *DC, *LexicalDC;
7025+
Error Err = ImportDeclContext(D, DC, LexicalDC);
7026+
auto LocationOrErr = importChecked(Err, D->getLocation());
7027+
auto NameDeclOrErr = importChecked(Err, D->getDeclName());
7028+
auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
7029+
auto ConstraintExpr = importChecked(Err, D->getConstraintExpr());
7030+
if (Err)
7031+
return std::move(Err);
7032+
7033+
ConceptDecl *To;
7034+
if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, LocationOrErr,
7035+
NameDeclOrErr, ToTemplateParameters,
7036+
ConstraintExpr))
7037+
return To;
7038+
To->setLexicalDeclContext(LexicalDC);
7039+
LexicalDC->addDeclInternal(To);
7040+
return To;
7041+
}
7042+
7043+
ExpectedDecl
7044+
ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
7045+
DeclContext *DC, *LexicalDC;
7046+
Error Err = ImportDeclContext(D, DC, LexicalDC);
7047+
auto RequiresLoc = importChecked(Err, D->getLocation());
7048+
if (Err)
7049+
return std::move(Err);
7050+
7051+
RequiresExprBodyDecl *To;
7052+
if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, RequiresLoc))
7053+
return To;
7054+
To->setLexicalDeclContext(LexicalDC);
7055+
LexicalDC->addDeclInternal(To);
7056+
return To;
7057+
}
7058+
7059+
ExpectedDecl ASTNodeImporter::VisitImplicitConceptSpecializationDecl(
7060+
ImplicitConceptSpecializationDecl *D) {
7061+
DeclContext *DC, *LexicalDC;
7062+
Error Err = ImportDeclContext(D, DC, LexicalDC);
7063+
auto ToSL = importChecked(Err, D->getLocation());
7064+
if (Err)
7065+
return std::move(Err);
7066+
7067+
SmallVector<TemplateArgument, 2> ToArgs(D->getTemplateArguments().size());
7068+
if (Error Err = ImportTemplateArguments(D->getTemplateArguments(), ToArgs))
7069+
return std::move(Err);
7070+
7071+
ImplicitConceptSpecializationDecl *To;
7072+
if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, ToSL, ToArgs))
7073+
return To;
7074+
To->setLexicalDeclContext(LexicalDC);
7075+
LexicalDC->addDeclInternal(To);
7076+
return To;
7077+
}
7078+
68367079
//----------------------------------------------------------------------------
68377080
// Import Statements
68387081
//----------------------------------------------------------------------------
@@ -9052,6 +9295,50 @@ ExpectedStmt ASTNodeImporter::VisitCXXFoldExpr(CXXFoldExpr *E) {
90529295
ToEllipsisLoc, ToRHS, ToRParenLoc, E->getNumExpansions());
90539296
}
90549297

9298+
ExpectedStmt ASTNodeImporter::VisitRequiresExpr(RequiresExpr *E) {
9299+
Error Err = Error::success();
9300+
auto RequiresKWLoc = importChecked(Err, E->getRequiresKWLoc());
9301+
auto RParenLoc = importChecked(Err, E->getRParenLoc());
9302+
auto RBraceLoc = importChecked(Err, E->getRBraceLoc());
9303+
9304+
auto Body = importChecked(Err, E->getBody());
9305+
auto LParenLoc = importChecked(Err, E->getLParenLoc());
9306+
if (Err)
9307+
return std::move(Err);
9308+
SmallVector<ParmVarDecl *, 4> LocalParameters(E->getLocalParameters().size());
9309+
if (Error Err =
9310+
ImportArrayChecked(E->getLocalParameters(), LocalParameters.begin()))
9311+
return std::move(Err);
9312+
SmallVector<concepts::Requirement *, 4> Requirements(
9313+
E->getRequirements().size());
9314+
if (Error Err =
9315+
ImportArrayChecked(E->getRequirements(), Requirements.begin()))
9316+
return std::move(Err);
9317+
return RequiresExpr::Create(Importer.getToContext(), RequiresKWLoc, Body,
9318+
LParenLoc, LocalParameters, RParenLoc,
9319+
Requirements, RBraceLoc);
9320+
}
9321+
9322+
ExpectedStmt
9323+
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
9324+
Error Err = Error::success();
9325+
auto CL = importChecked(Err, E->getConceptReference());
9326+
auto CSD = importChecked(Err, E->getSpecializationDecl());
9327+
if (Err)
9328+
return std::move(Err);
9329+
if (E->isValueDependent())
9330+
return ConceptSpecializationExpr::Create(
9331+
Importer.getToContext(), CL,
9332+
const_cast<ImplicitConceptSpecializationDecl *>(CSD), nullptr);
9333+
ConstraintSatisfaction Satisfaction;
9334+
if (Error Err =
9335+
ImportConstraintSatisfaction(E->getSatisfaction(), Satisfaction))
9336+
return std::move(Err);
9337+
return ConceptSpecializationExpr::Create(
9338+
Importer.getToContext(), CL,
9339+
const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
9340+
}
9341+
90559342
Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod,
90569343
CXXMethodDecl *FromMethod) {
90579344
Error ImportErrors = Error::success();

clang/lib/AST/ASTStructuralEquivalence.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
16091609
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
16101610
CXXMethodDecl *Method1,
16111611
CXXMethodDecl *Method2) {
1612+
if (!Method1 && !Method2)
1613+
return true;
1614+
if (!Method1 || !Method2)
1615+
return false;
1616+
16121617
bool PropertiesEqual =
16131618
Method1->getDeclKind() == Method2->getDeclKind() &&
16141619
Method1->getRefQualifier() == Method2->getRefQualifier() &&

0 commit comments

Comments
 (0)