summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Decl.h6
-rw-r--r--clang/include/clang/AST/DeclBase.h4
-rw-r--r--clang/include/clang/Sema/Lookup.h8
-rw-r--r--clang/lib/AST/DeclBase.cpp4
-rw-r--r--clang/lib/Sema/SemaLookup.cpp18
-rw-r--r--clang/test/Modules/Inputs/template-default-args/a.h4
-rw-r--r--clang/test/Modules/Inputs/template-default-args/b.h0
-rw-r--r--clang/test/Modules/Inputs/template-default-args/module.modulemap1
-rw-r--r--clang/test/Modules/template-default-args.cpp22
9 files changed, 60 insertions, 7 deletions
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 451f9da1b60..e06b58b37be 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -236,7 +236,11 @@ public:
bool isHidden() const { return Hidden; }
/// \brief Set whether this declaration is hidden from name lookup.
- void setHidden(bool Hide) { Hidden = Hide; }
+ void setHidden(bool Hide) {
+ assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
+ "declaration with no owning module can't be hidden");
+ Hidden = Hide;
+ }
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 5c382b0d578..f176e5479e1 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -637,6 +637,8 @@ public:
private:
Module *getOwningModuleSlow() const;
+protected:
+ bool hasLocalOwningModuleStorage() const;
public:
/// \brief Get the imported owning module, if this decl is from an imported
@@ -656,7 +658,7 @@ public:
return reinterpret_cast<Module *const *>(this)[-1];
}
void setLocalOwningModule(Module *M) {
- assert(!isFromASTFile() && Hidden &&
+ assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() &&
"should not have a cached owning module");
reinterpret_cast<Module **>(this)[-1] = M;
}
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index 5bfee8b0d03..97192b53fa4 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -302,10 +302,14 @@ public:
if (!D->isInIdentifierNamespace(IDNS))
return nullptr;
- if (isHiddenDeclarationVisible() || isVisible(getSema(), D))
+ if (isVisible(getSema(), D))
return D;
- return getAcceptableDeclSlow(D);
+ if (auto *Visible = getAcceptableDeclSlow(D))
+ return Visible;
+
+ // Even if hidden declarations are visible, prefer a visible declaration.
+ return isHiddenDeclarationVisible() ? D : nullptr;
}
private:
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 79cadcfcb16..70bd16ffdd5 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -80,6 +80,10 @@ Module *Decl::getOwningModuleSlow() const {
return getASTContext().getExternalSource()->getModule(getOwningModuleID());
}
+bool Decl::hasLocalOwningModuleStorage() const {
+ return getASTContext().getLangOpts().ModulesLocalVisibility;
+}
+
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: llvm_unreachable("Declaration not in DeclNodes.inc!");
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 2600e8e44d6..d0a55b57c61 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1180,6 +1180,16 @@ Module *Sema::getOwningModule(Decl *Entity) {
assert(!Entity->isFromASTFile() &&
"hidden entity from AST file has no owning module");
+ if (!getLangOpts().ModulesLocalVisibility) {
+ // If we're not tracking visibility locally, the only way a declaration
+ // can be hidden and local is if it's hidden because it's parent is (for
+ // instance, maybe this is a lazily-declared special member of an imported
+ // class).
+ auto *Parent = cast<NamedDecl>(Entity->getDeclContext());
+ assert(Parent->isHidden() && "unexpectedly hidden decl");
+ return getOwningModule(Parent);
+ }
+
// It's local and hidden; grab or compute its owning module.
M = Entity->getLocalOwningModule();
if (M)
@@ -1218,9 +1228,11 @@ Module *Sema::getOwningModule(Decl *Entity) {
}
void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) {
- auto *M = PP.getModuleContainingLocation(Loc);
- assert(M && "hidden definition not in any module");
- Context.mergeDefinitionIntoModule(ND, M);
+ if (auto *M = PP.getModuleContainingLocation(Loc))
+ Context.mergeDefinitionIntoModule(ND, M);
+ else
+ // We're not building a module; just make the definition visible.
+ ND->setHidden(false);
}
/// \brief Find the module in which the given declaration was defined.
diff --git a/clang/test/Modules/Inputs/template-default-args/a.h b/clang/test/Modules/Inputs/template-default-args/a.h
new file mode 100644
index 00000000000..1ef1ea5907b
--- /dev/null
+++ b/clang/test/Modules/Inputs/template-default-args/a.h
@@ -0,0 +1,4 @@
+template<typename T = int> struct A {};
+template<typename T> struct B {};
+template<typename T> struct C;
+template<typename T> struct D;
diff --git a/clang/test/Modules/Inputs/template-default-args/b.h b/clang/test/Modules/Inputs/template-default-args/b.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/clang/test/Modules/Inputs/template-default-args/b.h
diff --git a/clang/test/Modules/Inputs/template-default-args/module.modulemap b/clang/test/Modules/Inputs/template-default-args/module.modulemap
new file mode 100644
index 00000000000..6182e6b3eee
--- /dev/null
+++ b/clang/test/Modules/Inputs/template-default-args/module.modulemap
@@ -0,0 +1 @@
+module X { module A { header "a.h" } module B { header "b.h" } }
diff --git a/clang/test/Modules/template-default-args.cpp b/clang/test/Modules/template-default-args.cpp
new file mode 100644
index 00000000000..63187b8dc19
--- /dev/null
+++ b/clang/test/Modules/template-default-args.cpp
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -verify -fmodules-cache-path=%t -I %S/Inputs/template-default-args -std=c++11 %s
+//
+// expected-no-diagnostics
+
+template<typename T> struct A;
+template<typename T> struct B;
+template<typename T> struct C;
+template<typename T = int> struct D;
+
+#include "b.h"
+
+template<typename T = int> struct A {};
+template<typename T> struct B {};
+template<typename T = int> struct B;
+template<typename T = int> struct C;
+template<typename T> struct D {};
+
+A<> a;
+B<> b;
+extern C<> c;
+D<> d;
OpenPOWER on IntegriCloud