[ASTImporter] Add support to import some AST nodes:

* CXXOperatorCallExpr
* SizeOfPackExpr
* DependentTemplateSpecializationType
* DependentSizedArray
* CXXTypeidExpr
* Fix importing CXXTemporaryObjectExpr

Some of the changes are based on
https://github.com/haoNoQ/clang/blob/summary-ipa-draft/lib/AST/ASTImporter.cpp

Differential Revision: https://reviews.llvm.org/D42335

llvm-svn: 323589
This commit is contained in:
Gabor Horvath 2018-01-27 16:11:45 +00:00
parent 1ae296da36
commit c78d99a84b
2 changed files with 200 additions and 23 deletions

View File

@ -52,7 +52,7 @@ namespace clang {
QualType VisitConstantArrayType(const ConstantArrayType *T);
QualType VisitIncompleteArrayType(const IncompleteArrayType *T);
QualType VisitVariableArrayType(const VariableArrayType *T);
// FIXME: DependentSizedArrayType
QualType VisitDependentSizedArrayType(const DependentSizedArrayType *T);
// FIXME: DependentSizedExtVectorType
QualType VisitVectorType(const VectorType *T);
QualType VisitExtVectorType(const ExtVectorType *T);
@ -78,7 +78,8 @@ namespace clang {
QualType VisitElaboratedType(const ElaboratedType *T);
// FIXME: DependentNameType
QualType VisitPackExpansionType(const PackExpansionType *T);
// FIXME: DependentTemplateSpecializationType
QualType VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T);
QualType VisitObjCInterfaceType(const ObjCInterfaceType *T);
QualType VisitObjCObjectType(const ObjCObjectType *T);
QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
@ -294,6 +295,7 @@ namespace clang {
Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
Expr *VisitPackExpansionExpr(PackExpansionExpr *E);
Expr *VisitSizeOfPackExpr(SizeOfPackExpr *E);
Expr *VisitCXXNewExpr(CXXNewExpr *CE);
Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
@ -315,6 +317,7 @@ namespace clang {
Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
Expr *VisitTypeTraitExpr(TypeTraitExpr *E);
Expr *VisitCXXTypeidExpr(CXXTypeidExpr *E);
template<typename IIter, typename OIter>
@ -527,6 +530,24 @@ QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
Brackets);
}
QualType ASTNodeImporter::VisitDependentSizedArrayType(
const DependentSizedArrayType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
return QualType();
// SizeExpr may be null if size is not specified directly.
// For example, 'int a[]'.
Expr *Size = Importer.Import(T->getSizeExpr());
if (!Size && T->getSizeExpr())
return QualType();
SourceRange Brackets = Importer.Import(T->getBracketsRange());
return Importer.getToContext().getDependentSizedArrayType(
ToElementType, Size, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(),
Brackets);
}
QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
@ -827,6 +848,25 @@ QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
T->getNumExpansions());
}
QualType ASTNodeImporter::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T) {
NestedNameSpecifier *Qualifier = Importer.Import(T->getQualifier());
if (!Qualifier && T->getQualifier())
return QualType();
IdentifierInfo *Name = Importer.Import(T->getIdentifier());
if (!Name && T->getIdentifier())
return QualType();
SmallVector<TemplateArgument, 2> ToPack;
ToPack.reserve(T->getNumArgs());
if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToPack))
return QualType();
return Importer.getToContext().getDependentTemplateSpecializationType(
T->getKeyword(), Qualifier, Name, ToPack);
}
QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
ObjCInterfaceDecl *Class
= dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
@ -5709,6 +5749,11 @@ Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
if (T.isNull())
return nullptr;
TypeSourceInfo *TInfo = Importer.Import(CE->getTypeSourceInfo());
if (!TInfo)
return nullptr;
SmallVector<Expr *, 8> Args(CE->getNumArgs());
if (ImportContainerChecked(CE->arguments(), Args))
return nullptr;
@ -5718,18 +5763,11 @@ Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
if (!Ctor)
return nullptr;
return CXXTemporaryObjectExpr::Create(
Importer.getToContext(), T,
Importer.Import(CE->getLocStart()),
Ctor,
CE->isElidable(),
Args,
CE->hadMultipleCandidates(),
CE->isListInitialization(),
CE->isStdInitListInitialization(),
CE->requiresZeroInitialization(),
CE->getConstructionKind(),
Importer.Import(CE->getParenOrBraceRange()));
return new (Importer.getToContext()) CXXTemporaryObjectExpr(
Importer.getToContext(), Ctor, T, TInfo, Args,
Importer.Import(CE->getParenOrBraceRange()), CE->hadMultipleCandidates(),
CE->isListInitialization(), CE->isStdInitListInitialization(),
CE->requiresZeroInitialization());
}
Expr *
@ -5769,6 +5807,31 @@ Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
E->getNumExpansions());
}
Expr *ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
auto *Pack = cast_or_null<NamedDecl>(Importer.Import(E->getPack()));
if (!Pack)
return nullptr;
Optional<unsigned> Length;
if (!E->isValueDependent())
Length = E->getPackLength();
SmallVector<TemplateArgument, 8> PartialArguments;
if (E->isPartiallySubstituted()) {
if (ImportTemplateArguments(E->getPartialArguments().data(),
E->getPartialArguments().size(),
PartialArguments))
return nullptr;
}
return SizeOfPackExpr::Create(
Importer.getToContext(), Importer.Import(E->getOperatorLoc()), Pack,
Importer.Import(E->getPackLoc()), Importer.Import(E->getRParenLoc()),
Length, PartialArguments);
}
Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
QualType T = Importer.Import(CE->getType());
if (T.isNull())
@ -6093,16 +6156,9 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
return nullptr;
unsigned NumArgs = E->getNumArgs();
llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) {
Expr *FromArg = E->getArg(ai);
Expr *ToArg = Importer.Import(FromArg);
if (!ToArg)
return nullptr;
ToArgs[ai] = ToArg;
}
if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
Expr **ToArgs_Copied = new (Importer.getToContext())
Expr*[NumArgs];
@ -6110,6 +6166,13 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai)
ToArgs_Copied[ai] = ToArgs[ai];
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
return new (Importer.getToContext()) CXXOperatorCallExpr(
Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, T,
OCE->getValueKind(), Importer.Import(OCE->getRParenLoc()),
OCE->getFPFeatures());
}
return new (Importer.getToContext())
CallExpr(Importer.getToContext(), ToCallee,
llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(),
@ -6336,6 +6399,28 @@ Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), ToValue);
}
Expr *ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
QualType ToType = Importer.Import(E->getType());
if (ToType.isNull())
return nullptr;
if (E->isTypeOperand()) {
TypeSourceInfo *TSI = Importer.Import(E->getTypeOperandSourceInfo());
if (!TSI)
return nullptr;
return new (Importer.getToContext())
CXXTypeidExpr(ToType, TSI, Importer.Import(E->getSourceRange()));
}
Expr *Op = Importer.Import(E->getExprOperand());
if (!Op)
return nullptr;
return new (Importer.getToContext())
CXXTypeidExpr(ToType, Op, Importer.Import(E->getSourceRange()));
}
void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
for (auto *FromOverriddenMethod : FromMethod->overridden_methods())

View File

@ -484,6 +484,16 @@ TEST(ImportExpr, ImportVAArgExpr) {
vaArgExpr())))))));
}
TEST(ImportExpr, CXXTemporaryObjectExpr) {
MatchVerifier<Decl> Verifier;
testImport("struct C {};"
"void declToImport() { C c = C(); }",
Lang_CXX, "", Lang_CXX, Verifier,
functionDecl(hasBody(compoundStmt(has(
declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
has(materializeTemporaryExpr(has(implicitCastExpr(
has(cxxTemporaryObjectExpr())))))))))))))))));
}
TEST(ImportType, ImportAtomicType) {
MatchVerifier<Decl> Verifier;
@ -568,6 +578,50 @@ TEST(ImportType, ImportPackExpansion) {
declRefExpr())))))))));
}
const internal::VariadicDynCastAllOfMatcher<Type,
DependentTemplateSpecializationType>
dependentTemplateSpecializationType;
TEST(ImportType, ImportDependentTemplateSpecialization) {
MatchVerifier<Decl> Verifier;
testImport("template<typename T>"
"struct A;"
"template<typename T>"
"struct declToImport {"
" typename A<T>::template B<T> a;"
"};",
Lang_CXX, "", Lang_CXX, Verifier,
classTemplateDecl(has(cxxRecordDecl(has(
fieldDecl(hasType(dependentTemplateSpecializationType())))))));
}
const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
sizeOfPackExpr;
TEST(ImportExpr, ImportSizeOfPackExpr) {
MatchVerifier<Decl> Verifier;
testImport("template <typename... Ts>"
"void declToImport() {"
" const int i = sizeof...(Ts);"
"};"
"void g() { declToImport<int>(); }",
Lang_CXX11, "", Lang_CXX11, Verifier,
functionTemplateDecl(has(functionDecl(
hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
implicitCastExpr(has(sizeOfPackExpr())))))))))))));
testImport(
"template <typename... Ts>"
"using X = int[sizeof...(Ts)];"
"template <typename... Us>"
"struct Y {"
" X<Us..., int, double, int, Us...> f;"
"};"
"Y<float, int> declToImport;",
Lang_CXX11, "", Lang_CXX11, Verifier,
varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
}
/// \brief Matches __builtin_types_compatible_p:
/// GNU extension to check equivalent types
/// Given
@ -590,6 +644,24 @@ TEST(ImportExpr, ImportTypeTraitExpr) {
typeTraitExpr(hasType(asString("int"))))))));
}
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
TEST(ImportExpr, ImportCXXTypeidExpr) {
MatchVerifier<Decl> Verifier;
testImport(
"namespace std { class type_info {}; }"
"void declToImport() {"
" int x;"
" auto a = typeid(int); auto b = typeid(x);"
"}",
Lang_CXX11, "", Lang_CXX11, Verifier,
functionDecl(
hasDescendant(varDecl(
hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
hasDescendant(varDecl(
hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
}
TEST(ImportExpr, ImportTypeTraitExprValDep) {
MatchVerifier<Decl> Verifier;
testImport("template<typename T> struct declToImport {"
@ -712,5 +784,25 @@ TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
unless(has(cxxRecordDecl(hasName("declToImport"))))))));
}
TEST(ImportExpr, CXXOperatorCallExpr) {
MatchVerifier<Decl> Verifier;
testImport("class declToImport {"
" void f() { *this = declToImport(); }"
"};",
Lang_CXX, "", Lang_CXX, Verifier,
cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
}
TEST(ImportExpr, DependentSizedArrayType) {
MatchVerifier<Decl> Verifier;
testImport("template<typename T, int Size> class declToImport {"
" T data[Size];"
"};",
Lang_CXX, "", Lang_CXX, Verifier,
classTemplateDecl(has(cxxRecordDecl(
has(fieldDecl(hasType(dependentSizedArrayType())))))));
}
} // end namespace ast_matchers
} // end namespace clang