Improvements to the ASTImporter to support LLDB top-level Clang expressions.

The testcase for this is in LLDB, adeed by r264662.

This patch adds support for a variety of new expression types to the AST
importer, mostly related to C++.  It also adds support for importing lambdas
correctly, and adds support for importing the attributes attached to any Decl.

Finally, the patch adds a new templated function to ASTNodeImporter that imports
arbitrary arrays of importable things into a bump-allocated array attached to
getToContext().  This is a pattern we see at many places in ASTNodeImporter;
rather than do it slightly differently at each point, this function does it one
way.

<rdar://problem/22864976>

llvm-svn: 264669
This commit is contained in:
Sean Callanan 2016-03-28 21:43:01 +00:00
parent cc1ac8d125
commit 8bca996651
1 changed files with 124 additions and 26 deletions

View File

@ -224,8 +224,36 @@ namespace clang {
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
Expr *VisitCStyleCastExpr(CStyleCastExpr *E); Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
Expr *VisitCXXThisExpr(CXXThisExpr *E);
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitMemberExpr(MemberExpr *E);
Expr *VisitCallExpr(CallExpr *E); Expr *VisitCallExpr(CallExpr *E);
Expr *VisitInitListExpr(InitListExpr *E);
template <typename T, typename Iter> bool ImportArray(Iter B, Iter E, llvm::ArrayRef<T*> &ToArray) {
size_t NumElements = E - B;
SmallVector<T *, 1> ImportedElements(NumElements);
ASTImporter &_Importer = Importer;
bool Failed = false;
std::transform(B, E, ImportedElements.begin(),
[&_Importer, &Failed](T *Element) -> T* {
T *ToElement = _Importer.Import(Element);
if (Element && !ToElement)
Failed = true;
return ToElement;
});
if (Failed)
return false;
T **CopiedElements = new (Importer.getToContext()) T*[NumElements];
std::copy(ImportedElements.begin(), ImportedElements.end(), &CopiedElements[0]);
ToArray = llvm::ArrayRef<T*>(CopiedElements, NumElements);
return true;
}
}; };
} }
using namespace clang; using namespace clang;
@ -2683,11 +2711,26 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
RecordDecl *D2 = AdoptDecl; RecordDecl *D2 = AdoptDecl;
SourceLocation StartLoc = Importer.Import(D->getLocStart()); SourceLocation StartLoc = Importer.Import(D->getLocStart());
if (!D2) { if (!D2) {
if (isa<CXXRecordDecl>(D)) { CXXRecordDecl *D2CXX = nullptr;
CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(), if (CXXRecordDecl *DCXX = llvm::dyn_cast<CXXRecordDecl>(D)) {
D->getTagKind(), if (DCXX->isLambda()) {
DC, StartLoc, Loc, TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo());
Name.getAsIdentifierInfo()); D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(),
DC, TInfo, Loc,
DCXX->isDependentLambda(),
DCXX->isGenericLambda(),
DCXX->getLambdaCaptureDefault());
Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl());
if (DCXX->getLambdaContextDecl() && !CDecl)
return nullptr;
D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(),
CDecl);
} else {
D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
D->getTagKind(),
DC, StartLoc, Loc,
Name.getAsIdentifierInfo());
}
D2 = D2CXX; D2 = D2CXX;
D2->setAccess(D->getAccess()); D2->setAccess(D->getAccess());
} else { } else {
@ -4653,16 +4696,11 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
} }
Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
SmallVector<Stmt *, 4> ToStmts(S->size()); llvm::ArrayRef<Stmt *> ToStmts;
auto &_Importer = this->Importer;
std::transform(S->body_begin(), S->body_end(), ToStmts.begin(), if (!ImportArray(S->body_begin(), S->body_end(), ToStmts))
[&_Importer](Stmt *CS) -> Stmt * { return nullptr;
return _Importer.Import(CS);
});
for (Stmt *ToS : ToStmts) {
if (!ToS)
return nullptr;
}
SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc()); SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc());
return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(), return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(),
@ -5290,17 +5328,10 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
if (!ToCCD && E->getConstructor()) if (!ToCCD && E->getConstructor())
return nullptr; return nullptr;
size_t NumArgs = E->getNumArgs(); ArrayRef<Expr *> ToArgs;
SmallVector<Expr *, 1> ToArgs(NumArgs);
ASTImporter &_Importer = Importer; if (!ImportArray(E->arg_begin(), E->arg_end(), ToArgs))
std::transform(E->arg_begin(), E->arg_end(), ToArgs.begin(), return nullptr;
[&_Importer](Expr *AE) -> Expr * {
return _Importer.Import(AE);
});
for (Expr *ToA : ToArgs) {
if (!ToA)
return nullptr;
}
return CXXConstructExpr::Create(Importer.getToContext(), T, return CXXConstructExpr::Create(Importer.getToContext(), T,
Importer.Import(E->getLocation()), Importer.Import(E->getLocation()),
@ -5313,6 +5344,44 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Importer.Import(E->getParenOrBraceRange())); Importer.Import(E->getParenOrBraceRange()));
} }
Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
Expr *ToFn = Importer.Import(E->getCallee());
if (!ToFn)
return nullptr;
ArrayRef<Expr *> ToArgs;
if (!ImportArray(E->arg_begin(), E->arg_end(), ToArgs))
return nullptr;
return new (Importer.getToContext()) CXXMemberCallExpr(Importer.getToContext(), ToFn,
ToArgs, T, E->getValueKind(),
Importer.Import(E->getRParenLoc()));
}
Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
return new (Importer.getToContext())
CXXThisExpr(Importer.Import(E->getLocation()), T, E->isImplicit());
}
Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
return new (Importer.getToContext())
CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation()));
}
Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
QualType T = Importer.Import(E->getType()); QualType T = Importer.Import(E->getType());
if (T.isNull()) if (T.isNull())
@ -5381,6 +5450,28 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
Importer.Import(E->getRParenLoc())); Importer.Import(E->getRParenLoc()));
} }
Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
ArrayRef<Expr *> ToInits;
if (!ImportArray(E->inits().begin(), E->inits().end(), ToInits))
return nullptr;
InitListExpr *ToE = new (Importer.getToContext())
InitListExpr(Importer.getToContext(),
Importer.Import(E->getLBraceLoc()),
ToInits,
Importer.Import(E->getRBraceLoc()));
if (ToE)
ToE->setType(T);
return ToE;
}
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager, ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport) bool MinimalImport)
@ -5949,6 +6040,13 @@ void ASTImporter::CompleteDecl (Decl *D) {
} }
Decl *ASTImporter::Imported(Decl *From, Decl *To) { Decl *ASTImporter::Imported(Decl *From, Decl *To) {
if (From->hasAttrs()) {
for (Attr *FromAttr : From->getAttrs())
To->addAttr(FromAttr->clone(To->getASTContext()));
}
if (From->isUsed()) {
To->setIsUsed();
}
ImportedDecls[From] = To; ImportedDecls[From] = To;
return To; return To;
} }