[cfe-commits] r160395 - in /cfe/trunk: include/clang/AST/ASTImporter.h lib/AST/ASTImporter.cpp lib/AST/DeclBase.cpp
Douglas Gregor
dgregor at apple.com
Tue Jul 17 14:16:27 PDT 2012
Author: dgregor
Date: Tue Jul 17 16:16:27 2012
New Revision: 160395
URL: http://llvm.org/viewvc/llvm-project?rev=160395&view=rev
Log:
Teach the ASTImporter how to handle anonymous structs/unions
better. Fixes <rdar://problem/11466212>; the test (and back-ported
version of this code) were committed to LLDB in r160186.
Modified:
cfe/trunk/include/clang/AST/ASTImporter.h
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/AST/DeclBase.cpp
Modified: cfe/trunk/include/clang/AST/ASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=160395&r1=160394&r2=160395&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)
+++ cfe/trunk/include/clang/AST/ASTImporter.h Tue Jul 17 16:16:27 2012
@@ -271,7 +271,8 @@
/// \brief Determine whether the given types are structurally
/// equivalent.
- bool IsStructurallyEquivalent(QualType From, QualType To);
+ bool IsStructurallyEquivalent(QualType From, QualType To,
+ bool Complain = true);
};
}
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=160395&r1=160394&r2=160395&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Jul 17 16:16:27 2012
@@ -119,7 +119,8 @@
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
- bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord);
+ bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
+ bool Complain = true);
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
Decl *VisitDecl(Decl *D);
@@ -201,12 +202,16 @@
/// \brief Whether we're being strict about the spelling of types when
/// unifying two types.
bool StrictTypeSpelling;
-
+
+ /// \brief Whether to complain about failures.
+ bool Complain;
+
StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2,
llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls,
- bool StrictTypeSpelling = false)
+ bool StrictTypeSpelling = false,
+ bool Complain = true)
: C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls),
- StrictTypeSpelling(StrictTypeSpelling) { }
+ StrictTypeSpelling(StrictTypeSpelling), Complain(Complain) { }
/// \brief Determine whether the two declarations are structurally
/// equivalent.
@@ -223,10 +228,16 @@
public:
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
+ if (!Complain)
+ return DiagnosticBuilder::getEmpty();
+
return C1.getDiagnostics().Report(Loc, DiagID);
}
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
+ if (!Complain)
+ return DiagnosticBuilder::getEmpty();
+
return C2.getDiagnostics().Report(Loc, DiagID);
}
};
@@ -2008,10 +2019,11 @@
}
bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
- RecordDecl *ToRecord) {
+ RecordDecl *ToRecord, bool Complain) {
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
Importer.getToContext(),
- Importer.getNonEquivalentDecls());
+ Importer.getNonEquivalentDecls(),
+ false, Complain);
return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
}
@@ -2291,7 +2303,7 @@
// We may already have a record of the same name; try to find and match it.
RecordDecl *AdoptDecl = 0;
- if (!DC->isFunctionOrMethod() && SearchName) {
+ if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
llvm::SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(SearchName, FoundDecls);
@@ -2307,25 +2319,31 @@
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
- if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
+ if ((SearchName && !D->isCompleteDefinition())
+ || (D->isCompleteDefinition() &&
+ D->isAnonymousStructOrUnion()
+ == FoundDef->isAnonymousStructOrUnion() &&
+ IsStructuralMatch(D, FoundDef))) {
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// function.
// FIXME: For C++, we should also merge methods here.
return Importer.Imported(D, FoundDef);
}
- } else {
+ } else if (!D->isCompleteDefinition()) {
// We have a forward declaration of this type, so adopt that forward
// declaration rather than building a new one.
AdoptDecl = FoundRecord;
continue;
- }
+ } else if (!SearchName) {
+ continue;
+ }
}
ConflictingDecls.push_back(FoundDecls[I]);
}
- if (!ConflictingDecls.empty()) {
+ if (!ConflictingDecls.empty() && SearchName) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
ConflictingDecls.data(),
ConflictingDecls.size());
@@ -2351,6 +2369,8 @@
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(D2);
+ if (D->isAnonymousStructOrUnion())
+ D2->setAnonymousStructOrUnion(true);
}
Importer.Imported(D, D2);
@@ -2642,11 +2662,16 @@
if (IndirectFieldDecl *FoundField
= dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
if (Importer.IsStructurallyEquivalent(D->getType(),
- FoundField->getType())) {
+ FoundField->getType(),
+ Name)) {
Importer.Imported(D, FoundField);
return FoundField;
}
-
+
+ // If there are more anonymous fields to check, continue.
+ if (!Name && I < N-1)
+ continue;
+
Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
<< Name << D->getType() << FoundField->getType();
Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
@@ -4621,12 +4646,14 @@
return To;
}
-bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) {
+bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To,
+ bool Complain) {
llvm::DenseMap<const Type *, const Type *>::iterator Pos
= ImportedTypes.find(From.getTypePtr());
if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To))
return true;
- StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls);
+ StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls,
+ false, Complain);
return Ctx.IsStructurallyEquivalent(From, To);
}
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=160395&r1=160394&r2=160395&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Jul 17 16:16:27 2012
@@ -1196,23 +1196,25 @@
// If there's no external storage, just perform a normal lookup and copy
// the results.
- if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage()) {
+ if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) {
lookup_result LookupResults = lookup(Name);
Results.insert(Results.end(), LookupResults.first, LookupResults.second);
return;
}
// If we have a lookup table, check there first. Maybe we'll get lucky.
- if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
- StoredDeclsMap::iterator Pos = Map->find(Name);
- if (Pos != Map->end()) {
- Results.insert(Results.end(),
- Pos->second.getLookupResult().first,
- Pos->second.getLookupResult().second);
- return;
+ if (Name) {
+ if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ StoredDeclsMap::iterator Pos = Map->find(Name);
+ if (Pos != Map->end()) {
+ Results.insert(Results.end(),
+ Pos->second.getLookupResult().first,
+ Pos->second.getLookupResult().second);
+ return;
+ }
}
}
-
+
// Slow case: grovel through the declarations in our chain looking for
// matches.
for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
More information about the cfe-commits
mailing list