[ASTImporter] Implement some expression-related AST node import (part 2)

* Some code cleanup
* Add tests not present in http://reviews.llvm.org/D14286
* Integrate a test suite from Serge Pavlov (http://reviews.llvm.org/D14224)
* ArrayTypeTraitExpr: serialize sub-expression to avoid keeping it undefined
* Implement import of some nodes:
  - ArrayTypeTraitExpr
  - ExpressionTraitExpr
  - OpaqueValueExpr
  - ArraySubscriptExpr
  - ExplicitCastExpr
  - ImplicitValueInitExpr
  - OffsetOfExpr
  - CXXThisExpr
  - CXXThrowExpr
  - CXXNoexceptExpr
  - CXXDefaultArgExpr
  - CXXScalarValueInitExpr
  - CXXBindTemporaryExpr
  - CXXTemporaryObjectExpr
  - MaterializeTemporaryExpr
  - ExprWithCleanups

  - StaticAssertDecl
  - FriendDecl

  - DecayedType

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

llvm-svn: 282572
This commit is contained in:
Aleksei Sidorin 2016-09-28 10:16:56 +00:00
parent 37d757039d
commit a693b37e14
10 changed files with 846 additions and 46 deletions

View File

@ -24,6 +24,7 @@
namespace clang {
class ASTContext;
class CXXCtorInitializer;
class CXXBaseSpecifier;
class Decl;
class DeclContext;
class DiagnosticsEngine;
@ -39,7 +40,9 @@ namespace clang {
class ASTImporter {
public:
typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
typedef llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>
ImportedCXXBaseSpecifierMap;
private:
/// \brief The contexts we're importing to and from.
ASTContext &ToContext, &FromContext;
@ -68,7 +71,12 @@ namespace clang {
/// \brief Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
llvm::DenseMap<FileID, FileID> ImportedFileIDs;
/// \brief Mapping from the already-imported CXXBasesSpecifier in
/// the "from" source manager to the corresponding CXXBasesSpecifier
/// in the "to" source manager.
ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers;
/// \brief Imported, anonymous tag declarations that are missing their
/// corresponding typedefs.
SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
@ -212,8 +220,13 @@ namespace clang {
/// \returns the equivalent initializer in the "to" context.
CXXCtorInitializer *Import(CXXCtorInitializer *FromInit);
/// \brief Import the given CXXBaseSpecifier from the "from" context into
/// the "to" context.
///
/// \returns the equivalent CXXBaseSpecifier in the source manager of the
/// "to" context.
CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec);
/// \brief Import the definition of the given declaration, including all of
/// the declarations it contains.
///

View File

@ -166,6 +166,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend class ASTNodeImporter;
friend TrailingObjects;
};

View File

@ -40,6 +40,7 @@ namespace clang {
// Importing types
QualType VisitType(const Type *T);
QualType VisitBuiltinType(const BuiltinType *T);
QualType VisitDecayedType(const DecayedType *T);
QualType VisitComplexType(const ComplexType *T);
QualType VisitPointerType(const PointerType *T);
QualType VisitBlockPointerType(const BlockPointerType *T);
@ -88,6 +89,8 @@ namespace clang {
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
typedef DesignatedInitExpr::Designator Designator;
Designator ImportDesignator(const Designator &D);
@ -123,6 +126,8 @@ namespace clang {
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
TemplateArgumentLoc ImportTemplateArgumentLoc(
const TemplateArgumentLoc &TALoc, bool &Error);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
@ -136,6 +141,7 @@ namespace clang {
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
@ -152,6 +158,7 @@ namespace clang {
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
Decl *VisitFriendDecl(FriendDecl *D);
Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
@ -242,11 +249,25 @@ namespace clang {
Expr *VisitConditionalOperator(ConditionalOperator *E);
Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E);
Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E);
Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
Expr *VisitExplicitCastExpr(ExplicitCastExpr *E);
Expr *VisitOffsetOfExpr(OffsetOfExpr *OE);
Expr *VisitCXXThrowExpr(CXXThrowExpr *E);
Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
Expr *VisitCXXNewExpr(CXXNewExpr *CE);
Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
Expr *VisitCXXThisExpr(CXXThisExpr *E);
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
Expr *VisitMemberExpr(MemberExpr *E);
@ -272,13 +293,26 @@ namespace clang {
bool Failed = false;
std::transform(Ibegin, Iend, Obegin,
[&ImporterRef, &Failed](ItemT *From) -> ItemT * {
ItemT *To = ImporterRef.Import(From);
ItemT *To = cast_or_null<ItemT>(
ImporterRef.Import(From));
if (!To && From)
Failed = true;
return To;
});
return Failed;
}
template<typename InContainerTy, typename OutContainerTy>
bool ImportContainerChecked(const InContainerTy &InContainer,
OutContainerTy &OutContainer) {
return ImportArrayChecked(InContainer.begin(), InContainer.end(),
OutContainer.begin());
}
template<typename InContainerTy, typename OIter>
bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
}
};
}
@ -1611,6 +1645,14 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
llvm_unreachable("Invalid BuiltinType Kind!");
}
QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
QualType OrigT = Importer.Import(T->getOriginalType());
if (OrigT.isNull())
return QualType();
return Importer.getToContext().getDecayedType(OrigT);
}
QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
@ -2267,17 +2309,9 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
TemplateParameterList *Params) {
SmallVector<NamedDecl *, 4> ToParams;
ToParams.reserve(Params->size());
for (TemplateParameterList::iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
Decl *To = Importer.Import(*P);
if (!To)
return nullptr;
ToParams.push_back(cast<NamedDecl>(To));
}
SmallVector<NamedDecl *, 4> ToParams(Params->size());
if (ImportContainerChecked(*Params, ToParams))
return nullptr;
Expr *ToRequiresClause;
if (Expr *const R = Params->getRequiresClause()) {
@ -2367,6 +2401,31 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
llvm_unreachable("Invalid template argument kind");
}
TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
const TemplateArgumentLoc &TALoc, bool &Error) {
Error = false;
TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument());
TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
TemplateArgumentLocInfo ToInfo;
if (Arg.getKind() == TemplateArgument::Expression) {
Expr *E = Importer.Import(FromInfo.getAsExpr());
ToInfo = TemplateArgumentLocInfo(E);
if (!E)
Error = true;
} else if (Arg.getKind() == TemplateArgument::Type) {
if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
ToInfo = TemplateArgumentLocInfo(TSI);
else
Error = true;
} else {
ToInfo = TemplateArgumentLocInfo(
Importer.Import(FromInfo.getTemplateQualifierLoc()),
Importer.Import(FromInfo.getTemplateNameLoc()),
Importer.Import(FromInfo.getTemplateEllipsisLoc()));
}
return TemplateArgumentLoc(Arg, ToInfo);
}
bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs) {
@ -2481,6 +2540,35 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
return accessSpecDecl;
}
Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
DeclContext *DC = Importer.ImportContext(D->getDeclContext());
if (!DC)
return nullptr;
DeclContext *LexicalDC = DC;
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
Expr *AssertExpr = Importer.Import(D->getAssertExpr());
if (!AssertExpr)
return nullptr;
StringLiteral *FromMsg = D->getMessage();
StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
if (!ToMsg && FromMsg)
return nullptr;
StaticAssertDecl *ToD = StaticAssertDecl::Create(
Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
Importer.Import(D->getRParenLoc()), D->isFailed());
ToD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToD);
Importer.Imported(D, ToD);
return ToD;
}
Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
@ -3330,6 +3418,70 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
return ToIndirectField;
}
Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
// Import the major distinguishing characteristics of a declaration.
DeclContext *DC = Importer.ImportContext(D->getDeclContext());
DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext()
? DC : Importer.ImportContext(D->getLexicalDeclContext());
if (!DC || !LexicalDC)
return nullptr;
// Determine whether we've already imported this decl.
// FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
auto *RD = cast<CXXRecordDecl>(DC);
FriendDecl *ImportedFriend = RD->getFirstFriend();
StructuralEquivalenceContext Context(
Importer.getFromContext(), Importer.getToContext(),
Importer.getNonEquivalentDecls(), false, false);
while (ImportedFriend) {
if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
ImportedFriend->getFriendDecl()))
return Importer.Imported(D, ImportedFriend);
} else if (D->getFriendType() && ImportedFriend->getFriendType()) {
if (Importer.IsStructurallyEquivalent(
D->getFriendType()->getType(),
ImportedFriend->getFriendType()->getType(), true))
return Importer.Imported(D, ImportedFriend);
}
ImportedFriend = ImportedFriend->getNextFriend();
}
// Not found. Create it.
FriendDecl::FriendUnion ToFU;
if (NamedDecl *FriendD = D->getFriendDecl())
ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD));
else
ToFU = Importer.Import(D->getFriendType());
if (!ToFU)
return nullptr;
SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
TemplateParameterList **FromTPLists =
D->getTrailingObjects<TemplateParameterList *>();
for (unsigned I = 0; I < D->NumTPLists; I++) {
TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
if (!List)
return nullptr;
ToTPLists[I] = List;
}
FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getLocation()),
ToFU, Importer.Import(D->getFriendLoc()),
ToTPLists);
Importer.Imported(D, FrD);
RD->pushFriendDecl(FrD);
FrD->setAccess(D->getAccess());
FrD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(FrD);
return FrD;
}
Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Import the major distinguishing characteristics of an ivar.
DeclContext *DC, *LexicalDC;
@ -4886,11 +5038,10 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
}
SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin()))
if (ImportContainerChecked(S->outputs(), Exprs))
return nullptr;
if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(),
Exprs.begin() + S->getNumOutputs()))
if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
return nullptr;
StringLiteral *AsmStr = cast_or_null<StringLiteral>(
@ -4933,8 +5084,8 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin()))
if (ImportContainerChecked(S->body(), ToStmts))
return nullptr;
SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
@ -5388,7 +5539,7 @@ Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
return nullptr;
return new (Importer.getToContext()) GNUNullExpr(
T, Importer.Import(E->getExprLoc()));
T, Importer.Import(E->getLocStart()));
}
Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
@ -5402,7 +5553,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
return nullptr;
return new (Importer.getToContext()) PredefinedExpr(
Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL);
Importer.Import(E->getLocStart()), T, E->getIdentType(), SL);
}
Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
@ -5421,6 +5572,20 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
if (T.isNull())
return nullptr;
TemplateArgumentListInfo ToTAInfo;
TemplateArgumentListInfo *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
for (const auto &FromLoc : E->template_arguments()) {
bool Error = false;
TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error);
if (Error)
return nullptr;
ToTAInfo.addArgument(ToTALoc);
}
ResInfo = &ToTAInfo;
}
DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
Importer.Import(E->getQualifierLoc()),
Importer.Import(E->getTemplateKeywordLoc()),
@ -5428,8 +5593,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
E->refersToEnclosingVariableOrCapture(),
Importer.Import(E->getLocation()),
T, E->getValueKind(),
FoundD,
/*FIXME:TemplateArgs=*/nullptr);
FoundD, ResInfo);
if (E->hadMultipleCandidates())
DRE->setHadMultipleCandidates(true);
return DRE;
@ -5438,7 +5602,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return NULL;
return nullptr;
return new (Importer.getToContext()) ImplicitValueInitExpr(T);
}
@ -5607,8 +5771,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
SmallVector<Expr *, 4> Exprs(E->getNumExprs());
if (ImportArrayChecked(
E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin()))
if (ImportContainerChecked(E->exprs(), Exprs))
return nullptr;
return new (Importer.getToContext()) ParenListExpr(
@ -5746,6 +5909,38 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
T, E->getValueKind(), E->getObjectKind());
}
Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo());
if (!ToQueried)
return nullptr;
Expr *Dim = Importer.Import(E->getDimensionExpression());
if (!Dim && E->getDimensionExpression())
return nullptr;
return new (Importer.getToContext()) ArrayTypeTraitExpr(
Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
E->getValue(), Dim, Importer.Import(E->getLocEnd()), T);
}
Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
Expr *ToQueried = Importer.Import(E->getQueriedExpression());
if (!ToQueried)
return nullptr;
return new (Importer.getToContext()) ExpressionTraitExpr(
Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
E->getValue(), Importer.Import(E->getLocEnd()), T);
}
Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@ -5756,10 +5951,28 @@ Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
return nullptr;
return new (Importer.getToContext()) OpaqueValueExpr(
Importer.Import(E->getExprLoc()), T, E->getValueKind(),
Importer.Import(E->getLocation()), T, E->getValueKind(),
E->getObjectKind(), SourceExpr);
}
Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
Expr *ToLHS = Importer.Import(E->getLHS());
if (!ToLHS)
return nullptr;
Expr *ToRHS = Importer.Import(E->getRHS());
if (!ToRHS)
return nullptr;
return new (Importer.getToContext()) ArraySubscriptExpr(
ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(),
Importer.Import(E->getRBracketLoc()));
}
Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@ -5790,11 +6003,14 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
E->isFPContractable());
}
static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
if (E->path_empty()) return false;
// TODO: import cast paths
return true;
bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) {
for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
if (CXXBaseSpecifier *Spec = Importer.Import(*I))
Path.push_back(Spec);
else
return true;
}
return false;
}
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
@ -5814,7 +6030,7 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
SubExpr, &BasePath, E->getValueKind());
}
Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
@ -5831,11 +6047,319 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
if (ImportCastPath(E, BasePath))
return nullptr;
return CStyleCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
SubExpr, &BasePath, TInfo,
Importer.Import(E->getLParenLoc()),
Importer.Import(E->getRParenLoc()));
switch (E->getStmtClass()) {
case Stmt::CStyleCastExprClass: {
CStyleCastExpr *CCE = cast<CStyleCastExpr>(E);
return CStyleCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
SubExpr, &BasePath, TInfo,
Importer.Import(CCE->getLParenLoc()),
Importer.Import(CCE->getRParenLoc()));
}
case Stmt::CXXFunctionalCastExprClass: {
CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E);
return CXXFunctionalCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), TInfo,
E->getCastKind(), SubExpr, &BasePath,
Importer.Import(FCE->getLParenLoc()),
Importer.Import(FCE->getRParenLoc()));
}
case Stmt::ObjCBridgedCastExprClass: {
ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E);
return new (Importer.getToContext()) ObjCBridgedCastExpr(
Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
TInfo, SubExpr);
}
default:
break; // just fall through
}
CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E);
SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()),
RParenLoc = Importer.Import(Named->getRParenLoc());
SourceRange Brackets = Importer.Import(Named->getAngleBrackets());
switch (E->getStmtClass()) {
case Stmt::CXXStaticCastExprClass:
return CXXStaticCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
SubExpr, &BasePath, TInfo,
ExprLoc, RParenLoc, Brackets);
case Stmt::CXXDynamicCastExprClass:
return CXXDynamicCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
SubExpr, &BasePath, TInfo,
ExprLoc, RParenLoc, Brackets);
case Stmt::CXXReinterpretCastExprClass:
return CXXReinterpretCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), E->getCastKind(),
SubExpr, &BasePath, TInfo,
ExprLoc, RParenLoc, Brackets);
case Stmt::CXXConstCastExprClass:
return CXXConstCastExpr::Create(Importer.getToContext(), T,
E->getValueKind(), SubExpr, TInfo, ExprLoc,
RParenLoc, Brackets);
default:
llvm_unreachable("Cast expression of unsupported type!");
return nullptr;
}
}
Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
QualType T = Importer.Import(OE->getType());
if (T.isNull())
return nullptr;
SmallVector<OffsetOfNode, 4> Nodes;
for (int I = 0, E = OE->getNumComponents(); I < E; ++I) {
const OffsetOfNode &Node = OE->getComponent(I);
switch (Node.getKind()) {
case OffsetOfNode::Array:
Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()),
Node.getArrayExprIndex(),
Importer.Import(Node.getLocEnd())));
break;
case OffsetOfNode::Base: {
CXXBaseSpecifier *BS = Importer.Import(Node.getBase());
if (!BS && Node.getBase())
return nullptr;
Nodes.push_back(OffsetOfNode(BS));
break;
}
case OffsetOfNode::Field: {
FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
if (!FD)
return nullptr;
Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD,
Importer.Import(Node.getLocEnd())));
break;
}
case OffsetOfNode::Identifier: {
IdentifierInfo *ToII = Importer.Import(Node.getFieldName());
if (!ToII)
return nullptr;
Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII,
Importer.Import(Node.getLocEnd())));
break;
}
}
}
SmallVector<Expr *, 4> Exprs(OE->getNumExpressions());
for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) {
Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I));
if (!ToIndexExpr)
return nullptr;
Exprs[I] = ToIndexExpr;
}
TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo());
if (!TInfo && OE->getTypeSourceInfo())
return nullptr;
return OffsetOfExpr::Create(Importer.getToContext(), T,
Importer.Import(OE->getOperatorLoc()),
TInfo, Nodes, Exprs,
Importer.Import(OE->getRParenLoc()));
}
Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
Expr *Operand = Importer.Import(E->getOperand());
if (!Operand)
return nullptr;
CanThrowResult CanThrow;
if (E->isValueDependent())
CanThrow = CT_Dependent;
else
CanThrow = E->getValue() ? CT_Can : CT_Cannot;
return new (Importer.getToContext()) CXXNoexceptExpr(
T, Operand, CanThrow,
Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd()));
}
Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr && E->getSubExpr())
return nullptr;
return new (Importer.getToContext()) CXXThrowExpr(
SubExpr, T, Importer.Import(E->getThrowLoc()),
E->isThrownVariableInScope());
}
Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
Importer.Import(E->getParam()));
if (!Param)
return nullptr;
return CXXDefaultArgExpr::Create(
Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param);
}
Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo());
if (!TypeInfo)
return nullptr;
return new (Importer.getToContext()) CXXScalarValueInitExpr(
T, TypeInfo, Importer.Import(E->getRParenLoc()));
}
Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
return nullptr;
auto *Dtor = cast_or_null<CXXDestructorDecl>(
Importer.Import(const_cast<CXXDestructorDecl *>(
E->getTemporary()->getDestructor())));
if (!Dtor)
return nullptr;
ASTContext &ToCtx = Importer.getToContext();
CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor);
return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr);
}
Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
QualType T = Importer.Import(CE->getType());
if (T.isNull())
return nullptr;
SmallVector<Expr *, 8> Args(CE->getNumArgs());
if (ImportContainerChecked(CE->arguments(), Args))
return nullptr;
auto *Ctor = cast_or_null<CXXConstructorDecl>(
Importer.Import(CE->getConstructor()));
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()));
}
Expr *
ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
Expr *TempE = Importer.Import(E->GetTemporaryExpr());
if (!TempE)
return nullptr;
ValueDecl *ExtendedBy = cast_or_null<ValueDecl>(
Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
if (!ExtendedBy && E->getExtendingDecl())
return nullptr;
auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
T, TempE, E->isBoundToLvalueReference());
// FIXME: Should ManglingNumber get numbers associated with 'to' context?
ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber());
return ToMTE;
}
Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
QualType T = Importer.Import(CE->getType());
if (T.isNull())
return nullptr;
SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs());
if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
return nullptr;
FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>(
Importer.Import(CE->getOperatorNew()));
if (!OperatorNewDecl && CE->getOperatorNew())
return nullptr;
FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
Importer.Import(CE->getOperatorDelete()));
if (!OperatorDeleteDecl && CE->getOperatorDelete())
return nullptr;
Expr *ToInit = Importer.Import(CE->getInitializer());
if (!ToInit && CE->getInitializer())
return nullptr;
TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo());
if (!TInfo)
return nullptr;
Expr *ToArrSize = Importer.Import(CE->getArraySize());
if (!ToArrSize && CE->getArraySize())
return nullptr;
return new (Importer.getToContext()) CXXNewExpr(
Importer.getToContext(),
CE->isGlobalNew(),
OperatorNewDecl, OperatorDeleteDecl,
CE->doesUsualArrayDeleteWantSize(),
PlacementArgs,
Importer.Import(CE->getTypeIdParens()),
ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo,
Importer.Import(CE->getSourceRange()),
Importer.Import(CE->getDirectInitRange()));
}
Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
Importer.Import(E->getOperatorDelete()));
if (!OperatorDeleteDecl && E->getOperatorDelete())
return nullptr;
Expr *ToArg = Importer.Import(E->getArgument());
if (!ToArg && E->getArgument())
return nullptr;
return new (Importer.getToContext()) CXXDeleteExpr(
T, E->isGlobalDelete(),
E->isArrayForm(),
E->isArrayFormAsWritten(),
E->doesUsualArrayDeleteWantSize(),
OperatorDeleteDecl,
ToArg,
Importer.Import(E->getLocStart()));
}
Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
@ -5849,8 +6373,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
return nullptr;
SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(),
ToArgs.begin()))
if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
return CXXConstructExpr::Create(Importer.getToContext(), T,
@ -5864,6 +6387,24 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Importer.Import(E->getParenOrBraceRange()));
}
Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) {
Expr *SubExpr = Importer.Import(EWC->getSubExpr());
if (!SubExpr && EWC->getSubExpr())
return nullptr;
SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects());
for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++)
if (ExprWithCleanups::CleanupObject Obj =
cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I))))
Objs[I] = Obj;
else
return nullptr;
return ExprWithCleanups::Create(Importer.getToContext(),
SubExpr, EWC->cleanupsHaveSideEffects(),
Objs);
}
Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@ -5874,8 +6415,7 @@ Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
return nullptr;
SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
return new (Importer.getToContext()) CXXMemberCallExpr(
@ -5976,8 +6516,7 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
return nullptr;
llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
if (ImportArrayChecked(
ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin()))
if (ImportContainerChecked(ILE->inits(), Exprs))
return nullptr;
ASTContext &ToCtx = Importer.getToContext();
@ -6530,6 +7069,21 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
}
CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
if (Pos != ImportedCXXBaseSpecifiers.end())
return Pos->second;
CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
Import(BaseSpec->getSourceRange()),
BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
BaseSpec->getAccessSpecifierAsWritten(),
Import(BaseSpec->getTypeSourceInfo()),
Import(BaseSpec->getEllipsisLoc()));
ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
return Imported;
}
void ASTImporter::ImportDefinition(Decl *From) {
Decl *To = Import(From);
if (!To)

View File

@ -1575,6 +1575,7 @@ void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
E->Loc = Range.getBegin();
E->RParen = Range.getEnd();
E->QueriedType = GetTypeSourceInfo(Record, Idx);
E->Dimension = Reader.ReadSubExpr();
}
void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {

View File

@ -1576,6 +1576,7 @@ void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
Record.push_back(E->getValue());
Record.AddSourceRange(E->getSourceRange());
Record.AddTypeSourceInfo(E->getQueriedTypeSourceInfo());
Record.AddStmt(E->getDimensionExpression());
Code = serialization::EXPR_ARRAY_TYPE_TRAIT;
}

View File

@ -0,0 +1,26 @@
class C1 {
public:
C1();
~C1();
C1 *method_1() {
return this;
}
C1 method_2() {
return C1();
}
void method_3() {
const C1 &ref = C1();
}
};
class C11 : public C1 {
};
class C2 {
private:
int x;
friend class C3;
public:
static_assert(sizeof(x) == sizeof(int), "Error");
typedef class C2::C2 InjType;
};

View File

@ -0,0 +1,131 @@
// Integer literals
const char Ch1 = 'a';
const signed char Ch2 = 'b';
const unsigned char Ch3 = 'c';
const wchar_t Ch4 = L'd';
const signed wchar_t Ch5 = L'e';
const unsigned wchar_t Ch6 = L'f';
const short C1 = 12;
const unsigned short C2 = 13;
const int C3 = 12;
const unsigned int C4 = 13;
const long C5 = 22;
const unsigned long C6 = 23;
const long long C7 = 66;
const unsigned long long C8 = 67;
// String literals
const char str1[] = "ABCD";
const char str2[] = "ABCD" "0123";
const wchar_t wstr1[] = L"DEF";
const wchar_t wstr2[] = L"DEF" L"123";
// Boolean literals
const bool bval1 = true;
const bool bval2 = false;
// Floating Literals
const float F1 = 12.2F;
const double F2 = 1E4;
const long double F3 = 1.2E-3L;
// nullptr literal
const void *vptr = nullptr;
int glb_1[4] = { 10, 20, 30, 40 };
struct S1 {
int a;
int b[3];
};
struct S2 {
int c;
S1 d;
};
S2 glb_2 = { 22, .d.a = 44, .d.b[0] = 55, .d.b[1] = 66 };
void testNewThrowDelete() {
throw;
char *p = new char[10];
delete[] p;
}
int testArrayElement(int *x, int n) {
return x[n];
}
int testTernaryOp(int c, int x, int y) {
return c ? x : y;
}
S1 &testConstCast(const S1 &x) {
return const_cast<S1&>(x);
}
S1 &testStaticCast(S1 &x) {
return static_cast<S1&>(x);
}
S1 &testReinterpretCast(S1 &x) {
return reinterpret_cast<S1&>(x);
}
S1 &testDynamicCast(S1 &x) {
return dynamic_cast<S1&>(x);
}
int testScalarInit(int x) {
return int(x);
}
struct S {
float f;
double d;
};
struct T {
int i;
struct S s[10];
};
void testOffsetOf() {
__builtin_offsetof(struct T, s[2].d);
}
unsigned char asmFunc(unsigned char a, unsigned char b) {
unsigned int la = a;
unsigned int lb = b;
unsigned int bigres;
unsigned char res;
__asm__ ("0:\n1:\n" : [bigres] "=la"(bigres) : [la] "0"(la), [lb] "c"(lb) :
"edx", "cc");
res = bigres;
return res;
}
int testDefaultArg(int a = 2*2) {
return a;
}
template <typename T> // T has TemplateTypeParmType
void testTemplateTypeParmType(int i);
void useTemplateType() {
testTemplateTypeParmType<char>(4);
}
const bool ExpressionTrait = __is_lvalue_expr(1);
const unsigned ArrayRank = __array_rank(int[10][20]);
const unsigned ArrayExtent = __array_extent(int[10][20], 1);

View File

@ -0,0 +1,9 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/class3.cpp
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s
// expected-no-diagnostics
class C3 {
int method_1(C2 *x) {
return x->x;
}
};

View File

@ -0,0 +1,45 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/exprs3.cpp
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s
// expected-no-diagnostics
static_assert(Ch1 == 'a');
static_assert(Ch2 == 'b');
static_assert(Ch3 == 'c');
static_assert(Ch4 == L'd');
static_assert(Ch5 == L'e');
static_assert(Ch6 == L'f');
static_assert(C1 == 12);
static_assert(C2 == 13);
static_assert(C3 == 12);
static_assert(C4 == 13);
static_assert(C5 == 22L);
static_assert(C6 == 23L);
static_assert(C7 == 66LL);
static_assert(C8 == 67ULL);
static_assert(bval1 == true);
static_assert(bval2 == false);
static_assert(ExpressionTrait == false);
static_assert(ArrayRank == 2);
static_assert(ArrayExtent == 20);
void testImport(int *x, const S1 &cs1, S1 &s1) {
testNewThrowDelete();
testArrayElement(nullptr, 12);
testTernaryOp(0, 1, 2);
testConstCast(cs1);
testStaticCast(s1);
testReinterpretCast(s1);
testDynamicCast(s1);
testScalarInit(42);
testOffsetOf();
testDefaultArg(12);
useTemplateType();
}

View File

@ -456,5 +456,24 @@ TEST(ImportExpr, ImportInitListExpr) {
}
const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
TEST(ImportExpr, ImportVAArgExpr) {
MatchVerifier<Decl> Verifier;
EXPECT_TRUE(
testImport(
"void declToImport(__builtin_va_list list, ...) {"
" (void)__builtin_va_arg(list, int); }",
Lang_CXX, "", Lang_CXX, Verifier,
functionDecl(
hasBody(
compoundStmt(
has(
cStyleCastExpr(
hasSourceExpression(
vaArgExpr()))))))));
}
} // end namespace ast_matchers
} // end namespace clang