summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-10-23 02:17:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-10-23 02:17:46 +0000
commitfd8634a09de716f6de7b6699d6f4287056551525 (patch)
treed600133b3c296a3bd9256b843810c95921b2afd3
parentc89e4ca3c181b907562afa3e88be74366cf65bd2 (diff)
downloadbcm5719-llvm-fd8634a09de716f6de7b6699d6f4287056551525.tar.gz
bcm5719-llvm-fd8634a09de716f6de7b6699d6f4287056551525.zip
Make UsingShadowDecls redeclarable. This fixes some visibility problems with
modules. With this fixed, I no longer see any test regressions in the libc++ test suite when enabling a single-module module.map for libc++ (other than issues with my system headers). llvm-svn: 193219
-rw-r--r--clang/include/clang/AST/DeclCXX.h28
-rw-r--r--clang/include/clang/Sema/Sema.h6
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp44
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp21
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp2
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp16
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp1
-rw-r--r--clang/test/Modules/Inputs/module.map5
-rw-r--r--clang/test/Modules/Inputs/using-decl-a.h10
-rw-r--r--clang/test/Modules/Inputs/using-decl-b.h11
-rw-r--r--clang/test/Modules/using-decl.cpp8
11 files changed, 118 insertions, 34 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index bbf35604402..bb97b55f123 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2676,7 +2676,7 @@ public:
/// // Also creates a UsingShadowDecl for A::foo() in B
/// }
/// \endcode
-class UsingShadowDecl : public NamedDecl {
+class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
virtual void anchor();
/// The referenced declaration.
@@ -2699,6 +2699,17 @@ class UsingShadowDecl : public NamedDecl {
setImplicit();
}
+ typedef Redeclarable<UsingShadowDecl> redeclarable_base;
+ virtual UsingShadowDecl *getNextRedeclaration() {
+ return RedeclLink.getNext();
+ }
+ virtual UsingShadowDecl *getPreviousDeclImpl() {
+ return getPreviousDecl();
+ }
+ virtual UsingShadowDecl *getMostRecentDeclImpl() {
+ return getMostRecentDecl();
+ }
+
public:
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
@@ -2707,7 +2718,20 @@ public:
}
static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+
+ virtual UsingShadowDecl *getCanonicalDecl() {
+ return getFirstDecl();
+ }
+ virtual const UsingShadowDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
/// \brief Gets the underlying declaration which has been brought into the
/// local scope.
NamedDecl *getTargetDecl() const { return Underlying; }
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0c68e5c37a0..abbf512f3c1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3640,9 +3640,11 @@ public:
void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
- const LookupResult &PreviousDecls);
+ const LookupResult &PreviousDecls,
+ UsingShadowDecl *&PrevShadow);
UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
- NamedDecl *Target);
+ NamedDecl *Target,
+ UsingShadowDecl *PrevDecl);
bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
bool HasTypenameKeyword,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f5bb3511f22..221c53f03f6 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7073,20 +7073,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
/// \brief Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
-static bool
-IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
- bool &SuppressRedeclaration) {
- if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
- SuppressRedeclaration = false;
+static bool
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
+ if (D1->getCanonicalDecl() == D2->getCanonicalDecl())
return true;
- }
if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
- if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) {
- SuppressRedeclaration = true;
+ if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2))
return Context.hasSameType(TD1->getUnderlyingType(),
TD2->getUnderlyingType());
- }
return false;
}
@@ -7095,7 +7090,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
- const LookupResult &Previous) {
+ const LookupResult &Previous,
+ UsingShadowDecl *&PrevShadow) {
// Diagnose finding a decl which is not from a base class of the
// current class. We do this now because there are cases where this
// function will silently decide not to build a shadow decl, which
@@ -7155,16 +7151,22 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
NamedDecl *NonTag = 0, *Tag = 0;
+ bool FoundEquivalentDecl = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
- bool Result;
- if (IsEquivalentForUsingDecl(Context, D, Target, Result))
- return Result;
+ if (IsEquivalentForUsingDecl(Context, D, Target)) {
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
+ PrevShadow = Shadow;
+ FoundEquivalentDecl = true;
+ }
(isa<TagDecl>(D) ? Tag : NonTag) = D;
}
+ if (FoundEquivalentDecl)
+ return false;
+
if (Target->isFunctionOrFunctionTemplate()) {
FunctionDecl *FD;
if (isa<FunctionTemplateDecl>(Target))
@@ -7223,7 +7225,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
/// Builds a shadow declaration corresponding to a 'using' declaration.
UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
UsingDecl *UD,
- NamedDecl *Orig) {
+ NamedDecl *Orig,
+ UsingShadowDecl *PrevDecl) {
// If we resolved to another shadow declaration, just coalesce them.
NamedDecl *Target = Orig;
@@ -7231,16 +7234,18 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
}
-
+
UsingShadowDecl *Shadow
= UsingShadowDecl::Create(Context, CurContext,
UD->getLocation(), UD, Target);
UD->addShadowDecl(Shadow);
-
+
Shadow->setAccess(UD->getAccess());
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
Shadow->setInvalidDecl();
-
+
+ Shadow->setPreviousDecl(PrevDecl);
+
if (S)
PushOnScopeChains(Shadow, S);
else
@@ -7504,8 +7509,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- if (!CheckUsingShadowDecl(UD, *I, Previous))
- BuildUsingShadowDecl(S, UD, *I);
+ UsingShadowDecl *PrevDecl = 0;
+ if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
+ BuildUsingShadowDecl(S, UD, *I, PrevDecl);
}
return UD;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b5171640009..d0c3ac69144 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2152,19 +2152,22 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
I != E; ++I) {
UsingShadowDecl *Shadow = *I;
NamedDecl *InstTarget =
- cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
- Shadow->getLocation(),
- Shadow->getTargetDecl(),
- TemplateArgs));
+ cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
+ Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs));
if (!InstTarget)
return 0;
- if (CheckRedeclaration &&
- SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
- continue;
+ UsingShadowDecl *PrevDecl = 0;
+ if (CheckRedeclaration) {
+ if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
+ continue;
+ } else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) {
+ PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl(
+ Shadow->getLocation(), OldPrev, TemplateArgs));
+ }
- UsingShadowDecl *InstShadow
- = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+ UsingShadowDecl *InstShadow =
+ SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl);
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
if (isFunctionScope)
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 79bba0cb94f..a8176878dc4 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -165,6 +165,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXConversion:
+ case Decl::UsingShadow:
case Decl::Var:
case Decl::FunctionTemplate:
case Decl::ClassTemplate:
@@ -192,7 +193,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::NonTypeTemplateParm:
case Decl::TemplateTemplateParm:
case Decl::Using:
- case Decl::UsingShadow:
case Decl::ObjCMethod:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index e68c7fc6f9f..463af777986 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1134,12 +1134,14 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
}
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx));
D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx);
UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx);
if (Pattern)
Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern);
+ mergeRedeclarable(D, Redecl);
}
void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
@@ -2151,6 +2153,12 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
// FIXME: Also check the value is odr-equivalent.
return true;
+ // Using shadow declarations with the same target match.
+ if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) {
+ UsingShadowDecl *USY = cast<UsingShadowDecl>(Y);
+ return USX->getTargetDecl() == USY->getTargetDecl();
+ }
+
// FIXME: Many other cases to implement.
return false;
}
@@ -2258,6 +2266,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
VD->RedeclLink.setNext(cast<VarDecl>(previous));
} else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous));
+ } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
+ USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous));
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous));
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
@@ -2285,7 +2295,7 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
TD->RedeclLink
= Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- FD->RedeclLink
+ FD->RedeclLink
= Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
VD->RedeclLink
@@ -2294,6 +2304,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
TD->RedeclLink
= Redeclarable<TypedefNameDecl>::LatestDeclLink(
cast<TypedefNameDecl>(Latest));
+ } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
+ USD->RedeclLink
+ = Redeclarable<UsingShadowDecl>::LatestDeclLink(
+ cast<UsingShadowDecl>(Latest));
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
ID->RedeclLink
= Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 2d5ab7bb3a0..bee1786a0ac 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -938,6 +938,7 @@ void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
}
void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ VisitRedeclarable(D);
VisitNamedDecl(D);
Writer.AddDeclRef(D->getTargetDecl(), Record);
Writer.AddDeclRef(D->UsingOrNextShadow, Record);
diff --git a/clang/test/Modules/Inputs/module.map b/clang/test/Modules/Inputs/module.map
index 12da7a649ad..cb4d339f7e4 100644
--- a/clang/test/Modules/Inputs/module.map
+++ b/clang/test/Modules/Inputs/module.map
@@ -258,3 +258,8 @@ module warning {
module initializer_list {
header "initializer_list"
}
+
+module using_decl {
+ module a { header "using-decl-a.h" export * }
+ module b { header "using-decl-b.h" export * }
+}
diff --git a/clang/test/Modules/Inputs/using-decl-a.h b/clang/test/Modules/Inputs/using-decl-a.h
new file mode 100644
index 00000000000..85a4788e764
--- /dev/null
+++ b/clang/test/Modules/Inputs/using-decl-a.h
@@ -0,0 +1,10 @@
+typedef int using_decl_type;
+int using_decl_var;
+
+namespace UsingDecl {
+ using ::using_decl_type;
+ using ::using_decl_var;
+
+ namespace A { typedef int inner; }
+ using A::inner;
+}
diff --git a/clang/test/Modules/Inputs/using-decl-b.h b/clang/test/Modules/Inputs/using-decl-b.h
new file mode 100644
index 00000000000..b82526f39ff
--- /dev/null
+++ b/clang/test/Modules/Inputs/using-decl-b.h
@@ -0,0 +1,11 @@
+namespace UsingDecl {
+ namespace B { typedef int inner; }
+ using B::inner;
+}
+
+#include "using-decl-a.h"
+
+namespace UsingDecl {
+ using ::using_decl_type;
+ using ::using_decl_var;
+}
diff --git a/clang/test/Modules/using-decl.cpp b/clang/test/Modules/using-decl.cpp
new file mode 100644
index 00000000000..4432738f060
--- /dev/null
+++ b/clang/test/Modules/using-decl.cpp
@@ -0,0 +1,8 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify
+
+@import using_decl.a;
+
+// expected-no-diagnostics
+UsingDecl::using_decl_type x = UsingDecl::using_decl_var;
+UsingDecl::inner y = x;
OpenPOWER on IntegriCloud