From 478bfc77fc86289f70b33bdd1ffaf4eda49f906e Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sun, 10 Aug 2014 02:20:15 +0000 Subject: [PATCH] [modules] When considering merging a newly-declared typedef into an imported one, perform the import if the types match even if the imported declaration is hidden. Otherwise, NamedDecl::declarationReplaces will drop one of the name lookup entries, making the typedef effectively inaccessible from one of the modules that declared it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215306 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 39 ++++++++++++++++++- test/Modules/Inputs/merge-typedefs/a1.h | 8 ++++ test/Modules/Inputs/merge-typedefs/a2.h | 3 ++ test/Modules/Inputs/merge-typedefs/b1.h | 9 +++++ test/Modules/Inputs/merge-typedefs/b2.h | 3 ++ .../Inputs/merge-typedefs/module.modulemap | 9 +++++ test/Modules/merge-typedefs.cpp | 9 +++++ 7 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 test/Modules/Inputs/merge-typedefs/a1.h create mode 100644 test/Modules/Inputs/merge-typedefs/a2.h create mode 100644 test/Modules/Inputs/merge-typedefs/b1.h create mode 100644 test/Modules/Inputs/merge-typedefs/b2.h create mode 100644 test/Modules/Inputs/merge-typedefs/module.modulemap create mode 100644 test/Modules/merge-typedefs.cpp diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 5f65593aa8..85c88a3f57 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1725,6 +1725,43 @@ static void filterNonConflictingPreviousDecls(ASTContext &context, filter.done(); } +/// Typedef declarations don't have linkage, but they still denote the same +/// entity if their types are the same. +/// FIXME: This is notionally doing the same thing as ASTReaderDecl's +/// isSameEntity. +static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context, + TypedefNameDecl *Decl, + LookupResult &Previous) { + // This is only interesting when modules are enabled. + if (!Context.getLangOpts().Modules) + return; + + // Empty sets are uninteresting. + if (Previous.empty()) + return; + + LookupResult::Filter Filter = Previous.makeFilter(); + while (Filter.hasNext()) { + NamedDecl *Old = Filter.next(); + + // Non-hidden declarations are never ignored. + if (!Old->isHidden()) + continue; + + // Declarations of the same entity are not ignored, even if they have + // different linkages. + if (auto *OldTD = dyn_cast(Old)) + if (Context.hasSameType(OldTD->getUnderlyingType(), + Decl->getUnderlyingType())) + continue; + + if (!Old->isExternallyVisible()) + Filter.erase(); + } + + Filter.done(); +} + bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { QualType OldType; if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) @@ -4835,7 +4872,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, // in an outer scope, it isn't the same thing. FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false, /*AllowInlineNamespace*/false); - filterNonConflictingPreviousDecls(Context, NewTD, Previous); + filterNonConflictingPreviousTypedefDecls(Context, NewTD, Previous); if (!Previous.empty()) { Redeclaration = true; MergeTypedefNameDecl(NewTD, Previous); diff --git a/test/Modules/Inputs/merge-typedefs/a1.h b/test/Modules/Inputs/merge-typedefs/a1.h new file mode 100644 index 0000000000..cb8e5b4738 --- /dev/null +++ b/test/Modules/Inputs/merge-typedefs/a1.h @@ -0,0 +1,8 @@ +#ifndef A1_H +#define A1_H +namespace llvm { +class MachineBasicBlock; +template class DomTreeNodeBase; +typedef DomTreeNodeBase MachineDomTreeNode; +} +#endif diff --git a/test/Modules/Inputs/merge-typedefs/a2.h b/test/Modules/Inputs/merge-typedefs/a2.h new file mode 100644 index 0000000000..ba306663e3 --- /dev/null +++ b/test/Modules/Inputs/merge-typedefs/a2.h @@ -0,0 +1,3 @@ +#ifndef A2_H +#define A2_H +#endif diff --git a/test/Modules/Inputs/merge-typedefs/b1.h b/test/Modules/Inputs/merge-typedefs/b1.h new file mode 100644 index 0000000000..fba3a89c30 --- /dev/null +++ b/test/Modules/Inputs/merge-typedefs/b1.h @@ -0,0 +1,9 @@ +#ifndef B1_H +#define B1_H +#include "a2.h" +namespace llvm { +class MachineBasicBlock; +template class DomTreeNodeBase; +typedef DomTreeNodeBase MachineDomTreeNode; +} +#endif diff --git a/test/Modules/Inputs/merge-typedefs/b2.h b/test/Modules/Inputs/merge-typedefs/b2.h new file mode 100644 index 0000000000..75bd63affb --- /dev/null +++ b/test/Modules/Inputs/merge-typedefs/b2.h @@ -0,0 +1,3 @@ +#ifndef B2_H +#define B2_H +#endif diff --git a/test/Modules/Inputs/merge-typedefs/module.modulemap b/test/Modules/Inputs/merge-typedefs/module.modulemap new file mode 100644 index 0000000000..4858f1be63 --- /dev/null +++ b/test/Modules/Inputs/merge-typedefs/module.modulemap @@ -0,0 +1,9 @@ +module A { + module A1 { header "a1.h" export * } + module A2 { header "a2.h" export * } +} + +module B { + module B1 { header "b1.h" export * } + module B2 { header "b2.h" export * } +} diff --git a/test/Modules/merge-typedefs.cpp b/test/Modules/merge-typedefs.cpp new file mode 100644 index 0000000000..5d82177603 --- /dev/null +++ b/test/Modules/merge-typedefs.cpp @@ -0,0 +1,9 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -x c++ -I%S/Inputs/merge-typedefs -verify %s +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-typedefs -verify %s + +#include "b2.h" +#include "a1.h" + +// expected-no-diagnostics +llvm::MachineDomTreeNode *p; -- 2.40.0