diff options
| author | Aleksei Sidorin <a.sidorin@samsung.com> | 2018-01-26 11:36:54 +0000 |
|---|---|---|
| committer | Aleksei Sidorin <a.sidorin@samsung.com> | 2018-01-26 11:36:54 +0000 |
| commit | 8fc8510cb8dab5857e62870e976dfa7feca3fca7 (patch) | |
| tree | 987fca5b298b2c15fa7be4579f9ea381df60058b /clang/lib | |
| parent | 24f0fa34c2e8d01ce97008f0f664016378079a92 (diff) | |
| download | bcm5719-llvm-8fc8510cb8dab5857e62870e976dfa7feca3fca7.tar.gz bcm5719-llvm-8fc8510cb8dab5857e62870e976dfa7feca3fca7.zip | |
[ASTImporter] Support LambdaExprs and improve template support
Also, a number of style and bug fixes was done:
* ASTImporterTest: added sanity check for source node
* ExternalASTMerger: better lookup for template specializations
* ASTImporter: don't add templated declarations into DeclContext
* ASTImporter: introduce a helper, ImportTemplateArgumentListInfo getting SourceLocations
* ASTImporter: proper set ParmVarDecls for imported FunctionProtoTypeLoc
Differential Revision: https://reviews.llvm.org/D42301
llvm-svn: 323519
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 311 | ||||
| -rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 48 | ||||
| -rw-r--r-- | clang/lib/AST/ExternalASTMerger.cpp | 36 |
3 files changed, 334 insertions, 61 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 27b6ff1c516..aea044c8c49 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -97,6 +97,8 @@ namespace clang { typedef DesignatedInitExpr::Designator Designator; Designator ImportDesignator(const Designator &D); + Optional<LambdaCapture> ImportLambdaCapture(const LambdaCapture &From); + /// \brief What we should import from the definition. enum ImportDefinitionKind { @@ -127,16 +129,26 @@ namespace clang { bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind = IDK_Default); TemplateParameterList *ImportTemplateParameterList( - TemplateParameterList *Params); + TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc( const TemplateArgumentLoc &TALoc); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, - SmallVectorImpl<TemplateArgument> &ToArgs); + SmallVectorImpl<TemplateArgument> &ToArgs); + template <typename InContainerTy> bool ImportTemplateArgumentListInfo(const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo); + + template<typename InContainerTy> + bool ImportTemplateArgumentListInfo(SourceLocation FromLAngleLoc, + SourceLocation FromRAngleLoc, + const InContainerTy &Container, + TemplateArgumentListInfo &Result); + + bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); + bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, @@ -295,6 +307,7 @@ namespace clang { Expr *VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); + Expr *VisitLambdaExpr(LambdaExpr *LE); Expr *VisitInitListExpr(InitListExpr *E); Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); @@ -1045,7 +1058,6 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, = FromData.HasDeclaredCopyConstructorWithConstParam; ToData.HasDeclaredCopyAssignmentWithConstParam = FromData.HasDeclaredCopyAssignmentWithConstParam; - ToData.IsLambda = FromData.IsLambda; SmallVector<CXXBaseSpecifier *, 4> Bases; for (const auto &Base1 : FromCXX->bases()) { @@ -1256,6 +1268,9 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, return false; } +// We cannot use Optional<> pattern here and below because +// TemplateArgumentListInfo's operator new is declared as deleted so it cannot +// be stored in Optional. template <typename InContainerTy> bool ASTNodeImporter::ImportTemplateArgumentListInfo( const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) { @@ -1268,6 +1283,18 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo( return false; } +template <typename InContainerTy> +bool ASTNodeImporter::ImportTemplateArgumentListInfo( + SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, + const InContainerTy &Container, TemplateArgumentListInfo &Result) { + TemplateArgumentListInfo ToTAInfo(Importer.Import(FromLAngleLoc), + Importer.Import(FromRAngleLoc)); + if (ImportTemplateArgumentListInfo(Container, ToTAInfo)) + return true; + Result = ToTAInfo; + return false; +} + bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain) { // Eliminate a potential failure point where we attempt to re-import @@ -1918,16 +1945,16 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (DCXX->getLambdaContextDecl() && !CDecl) return nullptr; D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl); - } else if (DCXX->isInjectedClassName()) { - // We have to be careful to do a similar dance to the one in - // Sema::ActOnStartCXXMemberDeclarations - CXXRecordDecl *const PrevDecl = nullptr; - const bool DelayTypeCreation = true; - D2CXX = CXXRecordDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, - Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); - Importer.getToContext().getTypeDeclType( - D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC)); + } else if (DCXX->isInjectedClassName()) { + // We have to be careful to do a similar dance to the one in + // Sema::ActOnStartCXXMemberDeclarations + CXXRecordDecl *const PrevDecl = nullptr; + const bool DelayTypeCreation = true; + D2CXX = CXXRecordDecl::Create( + Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); + Importer.getToContext().getTypeDeclType( + D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC)); } else { D2CXX = CXXRecordDecl::Create(Importer.getToContext(), D->getTagKind(), @@ -1936,6 +1963,9 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } D2 = D2CXX; D2->setAccess(D->getAccess()); + D2->setLexicalDeclContext(LexicalDC); + if (!DCXX->getDescribedClassTemplate()) + LexicalDC->addDeclInternal(D2); Importer.Imported(D, D2); @@ -1964,11 +1994,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } else { D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, Name.getAsIdentifierInfo()); + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); } D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); if (PrevDecl) { @@ -2044,6 +2074,94 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { return ToEnumerator; } +bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, + FunctionDecl *ToFD) { + switch (FromFD->getTemplatedKind()) { + case FunctionDecl::TK_NonTemplate: + case FunctionDecl::TK_FunctionTemplate: + break; + + case FunctionDecl::TK_MemberSpecialization: { + auto *InstFD = cast_or_null<FunctionDecl>( + Importer.Import(FromFD->getInstantiatedFromMemberFunction())); + if (!InstFD) + return true; + + TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind(); + SourceLocation POI = Importer.Import( + FromFD->getMemberSpecializationInfo()->getPointOfInstantiation()); + ToFD->setInstantiationOfMemberFunction(InstFD, TSK); + ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + break; + } + + case FunctionDecl::TK_FunctionTemplateSpecialization: { + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + auto *Template = cast_or_null<FunctionTemplateDecl>( + Importer.Import(FTSInfo->getTemplate())); + if (!Template) + return true; + TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); + + // Import template arguments. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + SmallVector<TemplateArgument, 8> ToTemplArgs; + if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + ToTemplArgs)) + return true; + + TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( + Importer.getToContext(), ToTemplArgs); + + TemplateArgumentListInfo ToTAInfo; + const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; + if (FromTAArgsAsWritten) { + if (ImportTemplateArgumentListInfo( + FromTAArgsAsWritten->LAngleLoc, FromTAArgsAsWritten->RAngleLoc, + FromTAArgsAsWritten->arguments(), ToTAInfo)) + return true; + } + + SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); + + ToFD->setFunctionTemplateSpecialization( + Template, ToTAList, /* InsertPos= */ nullptr, + TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); + break; + } + + case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { + auto *FromInfo = FromFD->getDependentSpecializationInfo(); + UnresolvedSet<8> TemplDecls; + unsigned NumTemplates = FromInfo->getNumTemplates(); + for (unsigned I = 0; I < NumTemplates; I++) { + if (auto *ToFTD = cast_or_null<FunctionTemplateDecl>( + Importer.Import(FromInfo->getTemplate(I)))) + TemplDecls.addDecl(ToFTD); + else + return true; + } + + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + if (ImportTemplateArgumentListInfo( + FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), + llvm::makeArrayRef(FromInfo->getTemplateArgs(), + FromInfo->getNumTemplateArgs()), + ToTAInfo)) + return true; + + ToFD->setDependentTemplateSpecialization(Importer.getToContext(), + TemplDecls, ToTAInfo); + break; + } + default: + llvm_unreachable("All cases should be covered!"); + } + + return false; +} + Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Import the major distinguishing characteristics of this function. DeclContext *DC, *LexicalDC; @@ -2151,15 +2269,18 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Parameters.push_back(ToP); } - // Create the imported function. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); + if (D->getTypeSourceInfo() && !TInfo) + return nullptr; + + // Create the imported function. FunctionDecl *ToFunction = nullptr; SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), InnerLocStart, - NameInfo, T, TInfo, + NameInfo, T, TInfo, FromConstructor->isExplicit(), D->isInlineSpecified(), D->isImplicit(), @@ -2225,9 +2346,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Importer.Imported(D, ToFunction); // Set the parameters. - for (unsigned I = 0, N = Parameters.size(); I != N; ++I) { - Parameters[I]->setOwningFunction(ToFunction); - ToFunction->addDeclInternal(Parameters[I]); + for (ParmVarDecl *Param : Parameters) { + Param->setOwningFunction(ToFunction); + ToFunction->addDeclInternal(Param); } ToFunction->setParams(Parameters); @@ -2237,6 +2358,16 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setPreviousDecl(Recent); } + // We need to complete creation of FunctionProtoTypeLoc manually with setting + // params it refers to. + if (TInfo) { + if (auto ProtoLoc = + TInfo->getTypeLoc().IgnoreParens().getAs<FunctionProtoTypeLoc>()) { + for (unsigned I = 0, N = Parameters.size(); I != N; ++I) + ProtoLoc.setParam(I, Parameters[I]); + } + } + if (usedDifferentExceptionSpec) { // Update FunctionProtoType::ExtProtoInfo. QualType T = Importer.Import(D->getType()); @@ -2254,8 +2385,17 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // FIXME: Other bits to merge? + // If it is a template, import all related things. + if (ImportTemplateInformation(D, ToFunction)) + return nullptr; + // Add this function to the lexical context. - LexicalDC->addDeclInternal(ToFunction); + // NOTE: If the function is templated declaration, it should be not added into + // LexicalDC. But described template is imported during import of + // FunctionTemplateDecl (it happens later). So, we use source declaration + // to determine if we should add the result function. + if (!D->getDescribedFunctionTemplate()) + LexicalDC->addDeclInternal(ToFunction); if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod); @@ -2749,6 +2889,14 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { if (FromDefArg && !ToDefArg) return nullptr; + if (D->isObjCMethodParameter()) { + ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex()); + ToParm->setObjCDeclQualifier(D->getObjCDeclQualifier()); + } else { + ToParm->setScopeInfo(D->getFunctionScopeDepth(), + D->getFunctionScopeIndex()); + } + if (D->isUsed()) ToParm->setIsUsed(); @@ -3850,12 +3998,12 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { return nullptr; } - CXXRecordDecl *DTemplated = D->getTemplatedDecl(); - + CXXRecordDecl *FromTemplated = D->getTemplatedDecl(); + // Create the declaration that is being templated. - CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>( - Importer.Import(DTemplated)); - if (!D2Templated) + CXXRecordDecl *ToTemplated = cast_or_null<CXXRecordDecl>( + Importer.Import(FromTemplated)); + if (!ToTemplated) return nullptr; // Resolve possible cyclic import. @@ -3863,15 +4011,15 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { return AlreadyImported; // Create the class template declaration itself. - TemplateParameterList *TemplateParams - = ImportTemplateParameterList(D->getTemplateParameters()); + TemplateParameterList *TemplateParams = + ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) return nullptr; ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, Loc, Name, TemplateParams, - D2Templated); - D2Templated->setDescribedClassTemplate(D2); + ToTemplated); + ToTemplated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); @@ -3879,10 +4027,10 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // Note the relationship between the class templates. Importer.Imported(D, D2); - Importer.Imported(DTemplated, D2Templated); + Importer.Imported(FromTemplated, ToTemplated); - if (DTemplated->isCompleteDefinition() && - !D2Templated->isCompleteDefinition()) { + if (FromTemplated->isCompleteDefinition() && + !ToTemplated->isCompleteDefinition()) { // FIXME: Import definition! } @@ -3958,12 +4106,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Import TemplateArgumentListInfo TemplateArgumentListInfo ToTAInfo; auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); - for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) { - if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I])) - ToTAInfo.addArgument(*ToLoc); - else - return nullptr; - } + if (ImportTemplateArgumentListInfo(ASTTemplateArgs.arguments(), ToTAInfo)) + return nullptr; QualType CanonInjType = Importer.Import( PartialSpec->getInjectedSpecializationType()); @@ -4901,12 +5045,8 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - for (const auto &FromLoc : E->template_arguments()) { - if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc)) - ToTAInfo.addArgument(*ToTALoc); - else - return nullptr; - } + if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return nullptr; ResInfo = &ToTAInfo; } @@ -5861,11 +6001,10 @@ Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( if (BaseType.isNull()) return nullptr; - TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), - Importer.Import(E->getRAngleLoc())); - TemplateArgumentListInfo *ResInfo = nullptr; + TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), + E->template_arguments(), ToTAInfo)) return nullptr; ResInfo = &ToTAInfo; } @@ -5926,11 +6065,10 @@ Expr *ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return nullptr; } - TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), - Importer.Import(E->getRAngleLoc())); - TemplateArgumentListInfo *ResInfo = nullptr; + TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), + E->template_arguments(), ToTAInfo)) return nullptr; ResInfo = &ToTAInfo; } @@ -5981,6 +6119,73 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { Importer.Import(E->getRParenLoc())); } +Optional<LambdaCapture> +ASTNodeImporter::ImportLambdaCapture(const LambdaCapture &From) { + VarDecl *Var = nullptr; + if (From.capturesVariable()) { + Var = cast_or_null<VarDecl>(Importer.Import(From.getCapturedVar())); + if (!Var) + return None; + } + + return LambdaCapture(Importer.Import(From.getLocation()), From.isImplicit(), + From.getCaptureKind(), Var, + From.isPackExpansion() + ? Importer.Import(From.getEllipsisLoc()) + : SourceLocation()); +} + +Expr *ASTNodeImporter::VisitLambdaExpr(LambdaExpr *LE) { + CXXRecordDecl *FromClass = LE->getLambdaClass(); + auto *ToClass = dyn_cast_or_null<CXXRecordDecl>(Importer.Import(FromClass)); + if (!ToClass) + return nullptr; + + // NOTE: lambda classes are created with BeingDefined flag set up. + // It means that ImportDefinition doesn't work for them and we should fill it + // manually. + if (ToClass->isBeingDefined()) { + for (auto FromField : FromClass->fields()) { + auto *ToField = cast_or_null<FieldDecl>(Importer.Import(FromField)); + if (!ToField) + return nullptr; + } + } + + auto *ToCallOp = dyn_cast_or_null<CXXMethodDecl>( + Importer.Import(LE->getCallOperator())); + if (!ToCallOp) + return nullptr; + + ToClass->completeDefinition(); + + unsigned NumCaptures = LE->capture_size(); + SmallVector<LambdaCapture, 8> Captures; + Captures.reserve(NumCaptures); + for (const auto &FromCapture : LE->captures()) { + if (auto ToCapture = ImportLambdaCapture(FromCapture)) + Captures.push_back(*ToCapture); + else + return nullptr; + } + + SmallVector<Expr *, 8> InitCaptures(NumCaptures); + if (ImportContainerChecked(LE->capture_inits(), InitCaptures)) + return nullptr; + + return LambdaExpr::Create(Importer.getToContext(), ToClass, + Importer.Import(LE->getIntroducerRange()), + LE->getCaptureDefault(), + Importer.Import(LE->getCaptureDefaultLoc()), + Captures, + LE->hasExplicitParameters(), + LE->hasExplicitResultType(), + InitCaptures, + Importer.Import(LE->getLocEnd()), + LE->containsUnexpandedParameterPack()); +} + + Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { QualType T = Importer.Import(ILE->getType()); if (T.isNull()) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 0df8e5653f3..a563c7e2fa0 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1153,12 +1153,22 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, D2->getTemplateParameters()); } +static bool IsTemplateDeclCommonStructurallyEquivalent( + StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2) { + if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) + return false; + if (!D1->getIdentifier()) // Special name + if (D1->getNameAsString() != D2->getNameAsString()) + return false; + return IsStructurallyEquivalent(Ctx, D1->getTemplateParameters(), + D2->getTemplateParameters()); +} + static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, ClassTemplateDecl *D1, ClassTemplateDecl *D2) { // Check template parameters. - if (!IsStructurallyEquivalent(Context, D1->getTemplateParameters(), - D2->getTemplateParameters())) + if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2)) return false; // Check the templated declaration. @@ -1166,6 +1176,18 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, D2->getTemplatedDecl()); } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FunctionTemplateDecl *D1, + FunctionTemplateDecl *D2) { + // Check template parameters. + if (!IsTemplateDeclCommonStructurallyEquivalent(Context, D1, D2)) + return false; + + // Check the templated declaration. + return Context.IsStructurallyEquivalent(D1->getTemplatedDecl()->getType(), + D2->getTemplatedDecl()->getType()); +} + /// Determine structural equivalence of two declarations. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1, Decl *D2) { @@ -1293,6 +1315,7 @@ bool StructuralEquivalenceContext::Finish() { // Record/non-record mismatch. Equivalent = false; } + } else if (EnumDecl *Enum1 = dyn_cast<EnumDecl>(D1)) { if (EnumDecl *Enum2 = dyn_cast<EnumDecl>(D2)) { // Check for equivalent enum names. @@ -1309,6 +1332,7 @@ bool StructuralEquivalenceContext::Finish() { // Enum/non-enum mismatch Equivalent = false; } + } else if (TypedefNameDecl *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) { if (TypedefNameDecl *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) { if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), @@ -1320,17 +1344,30 @@ bool StructuralEquivalenceContext::Finish() { // Typedef/non-typedef mismatch. Equivalent = false; } + } else if (ClassTemplateDecl *ClassTemplate1 = dyn_cast<ClassTemplateDecl>(D1)) { if (ClassTemplateDecl *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) { - if (!::IsStructurallyEquivalent(ClassTemplate1->getIdentifier(), - ClassTemplate2->getIdentifier()) || - !::IsStructurallyEquivalent(*this, ClassTemplate1, ClassTemplate2)) + if (!::IsStructurallyEquivalent(*this, ClassTemplate1, + ClassTemplate2)) Equivalent = false; } else { // Class template/non-class-template mismatch. Equivalent = false; } + + } else if (FunctionTemplateDecl *FunctionTemplate1 = + dyn_cast<FunctionTemplateDecl>(D1)) { + if (FunctionTemplateDecl *FunctionTemplate2 = + dyn_cast<FunctionTemplateDecl>(D2)) { + if (!::IsStructurallyEquivalent(*this, FunctionTemplate1, + FunctionTemplate2)) + Equivalent = false; + } else { + // Class template/non-class-template mismatch. + Equivalent = false; + } + } else if (TemplateTypeParmDecl *TTP1 = dyn_cast<TemplateTypeParmDecl>(D1)) { if (TemplateTypeParmDecl *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) { @@ -1350,6 +1387,7 @@ bool StructuralEquivalenceContext::Finish() { // Kind mismatch. Equivalent = false; } + } else if (TemplateTemplateParmDecl *TTP1 = dyn_cast<TemplateTemplateParmDecl>(D1)) { if (TemplateTemplateParmDecl *TTP2 = diff --git a/clang/lib/AST/ExternalASTMerger.cpp b/clang/lib/AST/ExternalASTMerger.cpp index 6b75c51c642..91de8dbca05 100644 --- a/clang/lib/AST/ExternalASTMerger.cpp +++ b/clang/lib/AST/ExternalASTMerger.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ExternalASTMerger.h" using namespace clang; @@ -351,6 +352,27 @@ void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) { } } +template <typename DeclTy> +static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { + for (auto *Spec : D->specializations()) + if (!Importer->Import(Spec)) + return true; + return false; +} + +/// Imports specializations from template declarations that can be specialized. +static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) { + if (!isa<TemplateDecl>(D)) + return false; + if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D)) + return importSpecializations(FunctionTD, Importer); + else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D)) + return importSpecializations(ClassTD, Importer); + else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D)) + return importSpecializations(VarTD, Importer); + return false; +} + bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { llvm::SmallVector<NamedDecl *, 1> Decls; @@ -376,9 +398,17 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, Decls.reserve(Candidates.size()); for (const Candidate &C : Candidates) { - NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get())); - assert(d); - Decls.push_back(d); + Decl *LookupRes = C.first.get(); + ASTImporter *Importer = C.second; + NamedDecl *ND = cast_or_null<NamedDecl>(Importer->Import(LookupRes)); + assert(ND); + // If we don't import specialization, they are not available via lookup + // because the lookup result is imported TemplateDecl and it does not + // reference its specializations until they are imported explicitly. + bool IsSpecImportFailed = + importSpecializationsIfNeeded(LookupRes, Importer); + assert(!IsSpecImportFailed); + Decls.push_back(ND); } SetExternalVisibleDeclsForName(DC, Name, Decls); return true; |

