Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,10 @@ namespace clang {
ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E);
ExpectedStmt VisitRequiresExpr(RequiresExpr* E);
ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E);
ExpectedStmt
VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E);
ExpectedStmt VisitPseudoObjectExpr(PseudoObjectExpr *E);
ExpectedStmt VisitCXXParenListInitExpr(CXXParenListInitExpr *E);

// Helper for chaining together multiple imports. If an error is detected,
// subsequent imports will return default constructed nodes, so that failure
Expand Down Expand Up @@ -9273,6 +9277,50 @@ ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
}

ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
Error Err = Error::success();
auto ToType = importChecked(Err, E->getType());
auto ToPackLoc = importChecked(Err, E->getParameterPackLocation());
auto ToArgPack = importChecked(Err, E->getArgumentPack());
auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl());
if (Err)
return std::move(Err);

return new (Importer.getToContext()) SubstNonTypeTemplateParmPackExpr(
ToType, E->getValueKind(), ToPackLoc, ToArgPack, ToAssociatedDecl,
E->getIndex(), E->getFinal());
}

ExpectedStmt ASTNodeImporter::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
SmallVector<Expr *, 4> ToSemantics(E->getNumSemanticExprs());
if (Error Err = ImportContainerChecked(E->semantics(), ToSemantics))
return std::move(Err);
auto ToSyntOrErr = import(E->getSyntacticForm());
if (!ToSyntOrErr)
return ToSyntOrErr.takeError();
return PseudoObjectExpr::Create(Importer.getToContext(), *ToSyntOrErr,
ToSemantics, E->getResultExprIndex());
}

ExpectedStmt
ASTNodeImporter::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
Error Err = Error::success();
auto ToType = importChecked(Err, E->getType());
auto ToInitLoc = importChecked(Err, E->getInitLoc());
auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
auto ToEndLoc = importChecked(Err, E->getEndLoc());
if (Err)
return std::move(Err);

SmallVector<Expr *, 4> ToArgs(E->getInitExprs().size());
if (Error Err = ImportContainerChecked(E->getInitExprs(), ToArgs))
return std::move(Err);
return CXXParenListInitExpr::Create(Importer.getToContext(), ToArgs, ToType,
E->getUserSpecifiedInitExprs().size(),
ToInitLoc, ToBeginLoc, ToEndLoc);
}

Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
Error ImportErrors = Error::success();
Expand Down
66 changes: 66 additions & 0 deletions clang/unittests/AST/ASTImporterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3300,6 +3300,72 @@ TEST_P(ImportExpr, ConceptNestedNonInstantiationDependentRequirement) {
conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
}

TEST_P(ImportExpr, ImportSubstNonTypeTemplateParmPackExpr) {
MatchVerifier<Decl> Verifier;
const char *Code = R"(
template<auto ...> struct X {};
template<typename ...> struct Z {};

template<int ...N> struct E {
template<int ...M> using B = Z<X<N, M>...>;
template<int M1, int M2> E(B<M1, M2>);
};
using declToImport = E<1, 3>;
)";
testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
typedefNameDecl(hasName("declToImport")));
}

TEST_P(ImportExpr, ImportCXXParenListInitExpr) {
MatchVerifier<Decl> Verifier;
const char *Code = R"(
struct Node {
int val;
double d;
};
Node* declToImport() { return new Node(2, 3.14); }
)";
testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
functionDecl(hasName("declToImport")));
}

TEST_P(ImportExpr, ImportPseudoObjectExpr) {
MatchVerifier<Decl> Verifier;
const char *Code = R"(
namespace std {
struct strong_ordering {
int n;
constexpr operator int() const { return n; }
static const strong_ordering less, equal, greater;
};
constexpr strong_ordering strong_ordering::less{-1},
strong_ordering::equal{0}, strong_ordering::greater{1};
}

struct A {
std::strong_ordering operator<=>(const A&) const;
};
struct B {
bool operator==(const B&) const;
bool operator<(const B&) const;
};

template<typename T> struct Cmp : T {
std::strong_ordering operator<=>(const Cmp&) const = default;
};

void use(...);
void declToImport() {
use(
Cmp<A>() <=> Cmp<A>(),
Cmp<B>() <=> Cmp<B>()
);
}
)";
testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
functionDecl(hasName("declToImport")));
}

class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
public:
static constexpr auto DefaultCode = R"(
Expand Down