summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-10-07 08:02:11 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-10-07 08:02:11 +0000
commit0b87e0739e02b839ab80bf06ce89aab5cbf57bc5 (patch)
tree1d276238b170c13a7e362357dac517fdd049a57c /clang/lib
parent3f8f8c9dbd23e0da6e5d81a1ee957c1209ab0234 (diff)
downloadbcm5719-llvm-0b87e0739e02b839ab80bf06ce89aab5cbf57bc5.tar.gz
bcm5719-llvm-0b87e0739e02b839ab80bf06ce89aab5cbf57bc5.zip
When merging class definitions across modules in C++, merge together fields.
This change doesn't go all the way to making fields redeclarable; instead, it makes them 'mergeable', which means we can find the canonical declaration, but not much else (and for a declaration that's not from a module, the canonical declaration is always that declaration). llvm-svn: 192092
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp10
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp29
2 files changed, 38 insertions, 1 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a0b3894a086..6ec14720007 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -34,6 +34,10 @@
using namespace clang;
+Decl *clang::getPrimaryMergedDecl(Decl *D) {
+ return D->getASTContext().getPrimaryMergedDecl(D);
+}
+
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
@@ -3094,6 +3098,10 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
}
unsigned FieldDecl::getFieldIndex() const {
+ const FieldDecl *Canonical = getCanonicalDecl();
+ if (Canonical != this)
+ return Canonical->getFieldIndex();
+
if (CachedFieldIndex) return CachedFieldIndex - 1;
unsigned Index = 0;
@@ -3101,7 +3109,7 @@ unsigned FieldDecl::getFieldIndex() const {
for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I, ++Index)
- I->CachedFieldIndex = Index + 1;
+ I->getCanonicalDecl()->CachedFieldIndex = Index + 1;
assert(CachedFieldIndex && "failed to find field in parent");
return CachedFieldIndex - 1;
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index a5fb21cb66c..341f8eb068d 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -296,6 +296,9 @@ namespace clang {
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
RedeclarableResult &Redecl);
+ template<typename T>
+ void mergeMergeable(Mergeable<T> *D);
+
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
@@ -914,6 +917,7 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx))
Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
}
+ mergeMergeable(FD);
}
void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
@@ -1874,6 +1878,22 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing,
}
}
+/// \brief Attempts to merge the given declaration (D) with another declaration
+/// of the same entity, for the case where the entity is not actually
+/// redeclarable. This happens, for instance, when merging the fields of
+/// identical class definitions from two different modules.
+template<typename T>
+void ASTDeclReader::mergeMergeable(Mergeable<T> *D) {
+ // If modules are not available, there is no reason to perform this merge.
+ if (!Reader.getContext().getLangOpts().Modules)
+ return;
+
+ if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
+ if (T *Existing = ExistingRes)
+ Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D),
+ Existing->getCanonicalDecl());
+}
+
void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
VisitDecl(D);
unsigned NumVars = D->varlist_size();
@@ -2091,6 +2111,15 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
TemplateY->getTemplateParameters());
}
+ // Fields with the same name and the same type match.
+ if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) {
+ FieldDecl *FDY = cast<FieldDecl>(Y);
+ // FIXME: Diagnose if the types don't match. More generally, diagnose if we
+ // get a declaration in a class definition that isn't in the canonical class
+ // definition.
+ return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
+ }
+
// FIXME: Many other cases to implement.
return false;
}
OpenPOWER on IntegriCloud