Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -58,7 +58,7 @@ QualType VisitExtVectorType(const ExtVectorType *T); QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T); QualType VisitFunctionProtoType(const FunctionProtoType *T); - // FIXME: UnresolvedUsingType + QualType VisitUnresolvedUsingType(const UnresolvedUsingType *T); QualType VisitParenType(const ParenType *T); QualType VisitTypedefType(const TypedefType *T); QualType VisitTypeOfExprType(const TypeOfExprType *T); @@ -128,8 +128,8 @@ TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); - TemplateArgumentLoc ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc, bool &Error); + Optional ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl &ToArgs); @@ -142,10 +142,12 @@ bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); + Decl *VisitEmptyDecl(EmptyDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); + Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitTypeAliasDecl(TypeAliasDecl *D); @@ -170,6 +172,12 @@ Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D); + Decl *VisitUsingDecl(UsingDecl *D); + Decl *VisitUsingShadowDecl(UsingShadowDecl *D); + Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); @@ -563,6 +571,22 @@ return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } +QualType ASTNodeImporter::VisitUnresolvedUsingType( + const UnresolvedUsingType *T) { + UnresolvedUsingTypenameDecl *ToD = cast_or_null( + Importer.Import(T->getDecl())); + if (!ToD) + return QualType(); + + UnresolvedUsingTypenameDecl *ToPrevD = + cast_or_null( + Importer.Import(T->getDecl()->getPreviousDecl())); + if (!ToPrevD && T->getDecl()->getPreviousDecl()) + return QualType(); + + return Importer.getToContext().getTypeDeclType(ToD, ToPrevD); +} + QualType ASTNodeImporter::VisitParenType(const ParenType *T) { QualType ToInnerType = Importer.Import(T->getInnerType()); if (ToInnerType.isNull()) @@ -1163,9 +1187,8 @@ llvm_unreachable("Invalid template argument kind"); } -TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc, bool &Error) { - Error = false; +Optional +ASTNodeImporter::ImportTemplateArgumentLoc(const TemplateArgumentLoc &TALoc) { TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); TemplateArgumentLocInfo ToInfo; @@ -1173,12 +1196,12 @@ Expr *E = Importer.Import(FromInfo.getAsExpr()); ToInfo = TemplateArgumentLocInfo(E); if (!E) - Error = true; + return None; } else if (Arg.getKind() == TemplateArgument::Type) { if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) ToInfo = TemplateArgumentLocInfo(TSI); else - Error = true; + return None; } else { ToInfo = TemplateArgumentLocInfo( Importer.Import(FromInfo.getTemplateQualifierLoc()), @@ -1268,6 +1291,29 @@ return nullptr; } +Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { + // Import the context of this declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return nullptr; + } + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + ToD->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToD); + LexicalDC->addDeclInternal(ToD); + return ToD; +} + Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); @@ -1402,6 +1448,44 @@ return ToNamespace; } +Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + // Import the major distinguishing characteristics of this namespace. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *LookupD; + if (ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc)) + return nullptr; + if (LookupD) + return LookupD; + + // NOTE: No conflict resolution is done for namespace aliases now. + + NamespaceDecl *TargetDecl = cast_or_null( + Importer.Import(D->getNamespace())); + if (!TargetDecl) + return nullptr; + + IdentifierInfo *ToII = Importer.Import(D->getIdentifier()); + if (!ToII) + return nullptr; + + NestedNameSpecifierLoc ToQLoc = Importer.Import(D->getQualifierLoc()); + if (D->getQualifierLoc() && !ToQLoc) + return nullptr; + + NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), TargetDecl); + + ToD->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToD); + LexicalDC->addDeclInternal(ToD); + + return ToD; +} + Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; @@ -1734,6 +1818,31 @@ } D2 = D2CXX; D2->setAccess(D->getAccess()); + + Importer.Imported(D, D2); + + if (ClassTemplateDecl *FromDescribed = + DCXX->getDescribedClassTemplate()) { + ClassTemplateDecl *ToDescribed = cast_or_null( + Importer.Import(FromDescribed)); + if (!ToDescribed) + return nullptr; + D2CXX->setDescribedClassTemplate(ToDescribed); + + } else if (MemberSpecializationInfo *MemberInfo = + DCXX->getMemberSpecializationInfo()) { + TemplateSpecializationKind SK = + MemberInfo->getTemplateSpecializationKind(); + CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); + CXXRecordDecl *ToInst = + cast_or_null(Importer.Import(FromInst)); + if (FromInst && !ToInst) + return nullptr; + D2CXX->setInstantiationOfMemberClass(ToInst, SK); + D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( + Importer.Import(MemberInfo->getPointOfInstantiation())); + } + } else { D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, Name.getAsIdentifierInfo()); @@ -2852,6 +2961,176 @@ return ToLinkageSpec; } +Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclarationNameInfo NameInfo(Name, + Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), + NameInfo, D->hasTypename()); + ToUsing->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsing); + Importer.Imported(D, ToUsing); + + if (NamedDecl *FromPattern = + Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { + if (NamedDecl *ToPattern = + dyn_cast_or_null(Importer.Import(FromPattern))) + Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern); + else + return nullptr; + } + + for (UsingShadowDecl *FromShadow : D->shadows()) { + if (UsingShadowDecl *ToShadow = + dyn_cast_or_null(Importer.Import(FromShadow))) + ToUsing->addShadowDecl(ToShadow); + else + // FIXME: We return a nullptr here but the definition is already created + // and available with lookups. How to fix this?.. + return nullptr; + } + return ToUsing; +} + +Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + UsingDecl *ToUsing = dyn_cast_or_null( + Importer.Import(D->getUsingDecl())); + if (!ToUsing) + return nullptr; + + NamedDecl *ToTarget = dyn_cast_or_null( + Importer.Import(D->getTargetDecl())); + if (!ToTarget) + return nullptr; + + UsingShadowDecl *ToShadow = UsingShadowDecl::Create( + Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + + ToShadow->setLexicalDeclContext(LexicalDC); + ToShadow->setAccess(D->getAccess()); + Importer.Imported(D, ToShadow); + + if (UsingShadowDecl *FromPattern = + Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { + if (UsingShadowDecl *ToPattern = + dyn_cast_or_null(Importer.Import(FromPattern))) + Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow, + ToPattern); + else + return nullptr; + } + + LexicalDC->addDeclInternal(ToShadow); + + return ToShadow; +} + + +Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclContext *ToComAncestor = Importer.ImportContext(D->getCommonAncestor()); + if (!ToComAncestor) + return nullptr; + + NamespaceDecl *ToNominated = cast_or_null( + Importer.Import(D->getNominatedNamespace())); + if (!ToNominated) + return nullptr; + + UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + ToUsingDir->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsingDir); + Importer.Imported(D, ToUsingDir); + + return ToUsingDir; +} + +Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( + UnresolvedUsingValueDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc())); + + Importer.Imported(D, ToUsingValue); + ToUsingValue->setAccess(D->getAccess()); + ToUsingValue->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsingValue); + + return ToUsingValue; +} + +Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( + UnresolvedUsingTypenameDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc())); + + Importer.Imported(D, ToUsing); + ToUsing->setAccess(D->getAccess()); + ToUsing->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsing); + + return ToUsing; +} + + bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -3429,7 +3708,6 @@ CXXRecordDecl *DTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. - // Create the declaration that is being templated. CXXRecordDecl *D2Templated = cast_or_null( Importer.Import(DTemplated)); if (!D2Templated) @@ -3536,11 +3814,10 @@ TemplateArgumentListInfo ToTAInfo; auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) { - bool Error = false; - auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I], Error); - if (Error) + if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I])) + ToTAInfo.addArgument(*ToLoc); + else return nullptr; - ToTAInfo.addArgument(ToLoc); } QualType CanonInjType = Importer.Import( @@ -4419,11 +4696,10 @@ TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { for (const auto &FromLoc : E->template_arguments()) { - bool Error = false; - TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); - if (Error) + if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc)) + ToTAInfo.addArgument(*ToTALoc); + else return nullptr; - ToTAInfo.addArgument(ToTALoc); } ResInfo = &ToTAInfo; } Index: test/ASTMerge/namespace/Inputs/namespace1.cpp =================================================================== --- test/ASTMerge/namespace/Inputs/namespace1.cpp +++ test/ASTMerge/namespace/Inputs/namespace1.cpp @@ -15,3 +15,13 @@ namespace N3 { extern float z; } + +namespace AliasWithSameName = N3; + +namespace TestUnresolvedTypenameAndValueDecls { +template class Base { +public: + typedef T foo; + void bar(); +}; +} Index: test/ASTMerge/namespace/Inputs/namespace2.cpp =================================================================== --- test/ASTMerge/namespace/Inputs/namespace2.cpp +++ test/ASTMerge/namespace/Inputs/namespace2.cpp @@ -15,3 +15,46 @@ namespace N3 { extern double z; } + +namespace Enclosing { +namespace Nested { + const int z = 4; +} +} + +namespace ContainsInline { + inline namespace Inline { + const int z = 10; + } +} + +namespace TestAliasName = Enclosing::Nested; +// NOTE: There is no warning on this alias. +namespace AliasWithSameName = Enclosing::Nested; + +namespace TestUsingDecls { + +namespace A { +void foo(); +} +namespace B { +using A::foo; // <- a UsingDecl creating a UsingShadow +} + +}// end namespace TestUsingDecls + +namespace TestUnresolvedTypenameAndValueDecls { + +template class Base; +template class Derived : public Base { +public: + using typename Base::foo; + using Base::bar; + typedef typename Derived::foo NewUnresolvedUsingType; +}; + +} // end namespace TestUnresolvedTypenameAndValueDecls + +namespace TestUsingNamespace { + using namespace Enclosing; +} Index: test/ASTMerge/namespace/test.cpp =================================================================== --- test/ASTMerge/namespace/test.cpp +++ test/ASTMerge/namespace/test.cpp @@ -1,6 +1,17 @@ -// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/namespace1.cpp -// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/namespace2.cpp -// RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.1.ast %S/Inputs/namespace1.cpp +// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.2.ast %S/Inputs/namespace2.cpp +// RUN: not %clang_cc1 -std=c++1z -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s + +static_assert(TestAliasName::z == 4); +static_assert(ContainsInline::z == 10); + +void testImport() { + typedef TestUnresolvedTypenameAndValueDecls::Derived Imported; + Imported a; // Successfull instantiation + static_assert(sizeof(Imported::foo) == sizeof(int)); + static_assert(sizeof(TestUnresolvedTypenameAndValueDecls::Derived::NewUnresolvedUsingType) == sizeof(double)); +} + // CHECK: namespace2.cpp:16:17: error: external variable 'z' declared with incompatible types in different translation units ('double' vs. 'float') // CHECK: namespace1.cpp:16:16: note: declared here with type 'float'