[cfe-commits] r147778 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/AST/DeclBase.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp test/Modules/Inputs/namespaces-left.h test/Modules/Inputs/namespaces-right.h test/Modules/namespaces.cpp
Douglas Gregor
dgregor at apple.com
Mon Jan 9 09:30:44 PST 2012
Author: dgregor
Date: Mon Jan 9 11:30:44 2012
New Revision: 147778
URL: http://llvm.org/viewvc/llvm-project?rev=147778&view=rev
Log:
Implement redeclaration merging for namespaces defined in distinct
modules. Teach name lookup into namespaces to search in each of the
merged DeclContexts as well as the (now-primary) DeclContext. This
supports the common case where two different modules put something
into the same namespace.
Modified:
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/test/Modules/Inputs/namespaces-left.h
cfe/trunk/test/Modules/Inputs/namespaces-right.h
cfe/trunk/test/Modules/namespaces.cpp
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Jan 9 11:30:44 2012
@@ -514,6 +514,12 @@
NextInContextAndBits.setInt(Bits);
}
+ /// \brief Set the owning module ID.
+ void setOwningModuleID(unsigned ID) {
+ assert(isFromASTFile() && "Only works on a deserialized declaration");
+ *((unsigned*)this - 2) = ID;
+ }
+
public:
/// \brief Determine the availability of the given declaration.
@@ -573,7 +579,16 @@
return *((const unsigned*)this - 1);
return 0;
}
-
+
+ /// \brief Retrieve the global ID of the module that owns this particular
+ /// declaration.
+ unsigned getOwningModuleID() const {
+ if (isFromASTFile())
+ return *((const unsigned*)this - 2);
+
+ return 0;
+ }
+
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Jan 9 11:30:44 2012
@@ -45,14 +45,17 @@
unsigned ID,
unsigned Size) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
- // resulting pointer will still be 8-byte aligned. At present, we're only
- // using the latter 4 bytes of this storage.
+ // resulting pointer will still be 8-byte aligned.
void *Start = Context.Allocate(Size + 8);
void *Result = (char*)Start + 8;
- // Store the global declaration ID
- unsigned *IDPtr = (unsigned*)Result - 1;
- *IDPtr = ID;
+ unsigned *PrefixPtr = (unsigned *)Result - 2;
+
+ // Zero out the first 4 bytes; this is used to store the owning module ID.
+ PrefixPtr[0] = 0;
+
+ // Store the global declaration ID in the second 4 bytes.
+ PrefixPtr[1] = ID;
return Result;
}
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Jan 9 11:30:44 2012
@@ -4808,15 +4808,17 @@
/// declaration context.
class DeclContextNameLookupVisitor {
ASTReader &Reader;
+ llvm::SmallVectorImpl<const DeclContext *> &Contexts;
const DeclContext *DC;
DeclarationName Name;
SmallVectorImpl<NamedDecl *> &Decls;
public:
DeclContextNameLookupVisitor(ASTReader &Reader,
- const DeclContext *DC, DeclarationName Name,
+ SmallVectorImpl<const DeclContext *> &Contexts,
+ DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Decls)
- : Reader(Reader), DC(DC), Name(Name), Decls(Decls) { }
+ : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
static bool visit(ModuleFile &M, void *UserData) {
DeclContextNameLookupVisitor *This
@@ -4824,11 +4826,20 @@
// Check whether we have any visible declaration information for
// this context in this module.
- ModuleFile::DeclContextInfosMap::iterator Info
- = M.DeclContextInfos.find(This->DC);
- if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData)
- return false;
+ ModuleFile::DeclContextInfosMap::iterator Info;
+ bool FoundInfo = false;
+ for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+ Info = M.DeclContextInfos.find(This->Contexts[I]);
+ if (Info != M.DeclContextInfos.end() &&
+ Info->second.NameLookupTableData) {
+ FoundInfo = true;
+ break;
+ }
+ }
+ if (!FoundInfo)
+ return false;
+
// Look for this name within this module.
ASTDeclContextNameLookupTable *LookupTable =
(ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData;
@@ -4870,7 +4881,24 @@
DeclContext::lookup_iterator(0));
SmallVector<NamedDecl *, 64> Decls;
- DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls);
+
+ // Compute the declaration contexts we need to look into. Multiple such
+ // declaration contexts occur when two declaration contexts from disjoint
+ // modules get merged, e.g., when two namespaces with the same name are
+ // independently defined in separate modules.
+ SmallVector<const DeclContext *, 2> Contexts;
+ Contexts.push_back(DC);
+
+ if (DC->isNamespace()) {
+ MergedDeclsMap::iterator Merged
+ = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Merged != MergedDecls.end()) {
+ for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ }
+ }
+
+ DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
++NumVisibleDeclContextsRead;
SetExternalVisibleDeclsForName(DC, Name, Decls);
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Jan 9 11:30:44 2012
@@ -369,6 +369,9 @@
// Determine whether this declaration is part of a (sub)module. If so, it
// may not yet be visible.
if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
+ // Store the owning submodule ID in the declaration.
+ D->setOwningModuleID(SubmoduleID);
+
// Module-private declarations are never visible, so there is no work to do.
if (!D->isModulePrivate()) {
if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
@@ -972,7 +975,8 @@
D->setInline(Record[Idx++]);
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
-
+ mergeRedeclarable(D, Redecl);
+
if (Redecl.getFirstID() == ThisDeclID) {
// FIXME: If there's already an anonymous namespace, do we merge it with
// this one? Or do we, when loading modules, just forget about anonymous
@@ -1232,7 +1236,7 @@
RedeclKind Kind = (RedeclKind)Record[Idx++];
// Determine the first declaration ID.
- DeclID FirstDeclID;
+ DeclID FirstDeclID = 0;
switch (Kind) {
case FirstDeclaration: {
FirstDeclID = ThisDeclID;
@@ -1489,7 +1493,7 @@
enum RedeclKind { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
- DeclID FirstDeclID;
+ DeclID FirstDeclID = 0;
switch (Kind) {
case FirstDeclaration:
FirstDeclID = ThisDeclID;
@@ -1545,6 +1549,13 @@
D->RedeclLink
= typename Redeclarable<T>::PreviousDeclLink(ExistingCanon);
+ // When we merge a namespace, update its pointer to the first namespace.
+ if (NamespaceDecl *Namespace
+ = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
+ Namespace->AnonOrFirstNamespaceAndInline.setPointer(
+ static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
+ }
+
// Don't introduce DCanon into the set of pending declaration chains.
Redecl.suppress();
@@ -1719,6 +1730,12 @@
VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
}
+ // Namespaces with the same name and inlinedness match.
+ if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
+ NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y);
+ return NamespaceX->isInline() == NamespaceY->isInline();
+ }
+
// FIXME: Many other cases to implement.
return false;
}
Modified: cfe/trunk/test/Modules/Inputs/namespaces-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/namespaces-left.h?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/namespaces-left.h (original)
+++ cfe/trunk/test/Modules/Inputs/namespaces-left.h Mon Jan 9 11:30:44 2012
@@ -9,3 +9,19 @@
namespace N2 {
float& f(float);
}
+
+
+
+
+
+namespace N5 {
+ int &f(int);
+}
+
+namespace N6 {
+ int &f(int);
+}
+
+namespace N7 {
+ int &f(int);
+}
Modified: cfe/trunk/test/Modules/Inputs/namespaces-right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/namespaces-right.h?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/namespaces-right.h (original)
+++ cfe/trunk/test/Modules/Inputs/namespaces-right.h Mon Jan 9 11:30:44 2012
@@ -16,3 +16,14 @@
double& f(double);
}
+namespace N5 {
+ double &f(double);
+}
+
+namespace N6 {
+ double &f(double);
+}
+
+namespace N7 {
+ double &f(double);
+}
Modified: cfe/trunk/test/Modules/namespaces.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/namespaces.cpp?rev=147778&r1=147777&r2=147778&view=diff
==============================================================================
--- cfe/trunk/test/Modules/namespaces.cpp (original)
+++ cfe/trunk/test/Modules/namespaces.cpp Mon Jan 9 11:30:44 2012
@@ -1,6 +1,10 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs %s -verify
+namespace N6 {
+ char &f(char);
+}
+
@import namespaces_left;
@import namespaces_right;
@@ -13,3 +17,20 @@
double &dr1 = N2::f(1.0);
double &dr2 = N3::f(1.0);
}
+
+// Test namespaces merged without a common first declaration.
+namespace N5 {
+ char &f(char);
+}
+
+void testMerged() {
+ int &ir1 = N5::f(17);
+ int &ir2 = N6::f(17);
+ int &ir3 = N7::f(17);
+ double &fr1 = N5::f(1.0);
+ double &fr2 = N6::f(1.0);
+ double &fr3 = N7::f(1.0);
+ char &cr1 = N5::f('a');
+ char &cr2 = N6::f('b');
+}
+
More information about the cfe-commits
mailing list