}
return 0;
+}
+
+bool serialization::isRedeclarableDeclKind(unsigned Kind) {
+ switch (static_cast<Decl::Kind>(Kind)) {
+ case Decl::TranslationUnit: // Special case of a "merged" declaration.
+ case Decl::Namespace:
+ case Decl::NamespaceAlias: // FIXME: Not yet redeclarable, but will be.
+ case Decl::Typedef:
+ case Decl::TypeAlias:
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::Var:
+ case Decl::FunctionTemplate:
+ case Decl::ClassTemplate:
+ case Decl::TypeAliasTemplate:
+ case Decl::ObjCProtocol:
+ case Decl::ObjCInterface:
+ return true;
+
+ // Never redeclarable.
+ case Decl::UsingDirective:
+ case Decl::Label:
+ case Decl::UnresolvedUsingTypename:
+ case Decl::TemplateTypeParm:
+ case Decl::EnumConstant:
+ case Decl::UnresolvedUsingValue:
+ case Decl::IndirectField:
+ case Decl::Field:
+ case Decl::ObjCIvar:
+ case Decl::ObjCAtDefsField:
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ case Decl::NonTypeTemplateParm:
+ case Decl::TemplateTemplateParm:
+ case Decl::Using:
+ case Decl::UsingShadow:
+ case Decl::ObjCMethod:
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCProperty:
+ case Decl::ObjCCompatibleAlias:
+ case Decl::LinkageSpec:
+ case Decl::ObjCPropertyImpl:
+ case Decl::FileScopeAsm:
+ case Decl::AccessSpec:
+ case Decl::Friend:
+ case Decl::FriendTemplate:
+ case Decl::StaticAssert:
+ case Decl::Block:
+ case Decl::ClassScopeFunctionSpecialization:
+ case Decl::Import:
+ return false;
+ }
+ llvm_unreachable("Unhandled declaration kind");
}
/// multiple definitions.
const Decl *getDefinitiveDeclContext(const DeclContext *DC);
+/// \brief Determine whether the given declaration kind is redeclarable.
+bool isRedeclarableDeclKind(unsigned Kind);
+
} // namespace serialization
} // namespace clang
ASTReader &Reader;
GlobalDeclID FirstID;
mutable bool Owning;
+ Decl::Kind DeclKind;
void operator=(RedeclarableResult &) LLVM_DELETED_FUNCTION;
public:
- RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID)
- : Reader(Reader), FirstID(FirstID), Owning(true) { }
+ RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
+ Decl::Kind DeclKind)
+ : Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { }
RedeclarableResult(const RedeclarableResult &Other)
- : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning)
+ : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) ,
+ DeclKind(Other.DeclKind)
{
Other.Owning = false;
}
~RedeclarableResult() {
- // FIXME: We want to suppress this when the declaration is local to
- // a function, since there's no reason to search other AST files
- // for redeclarations (they can't exist). However, this is hard to
- // do locally because the declaration hasn't necessarily loaded its
- // declaration context yet. Also, local externs still have the function
- // as their (semantic) declaration context, which is wrong and would
- // break this optimize.
-
- if (FirstID && Owning && Reader.PendingDeclChainsKnown.insert(FirstID))
+ if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) &&
+ Reader.PendingDeclChainsKnown.insert(FirstID))
Reader.PendingDeclChains.push_back(FirstID);
}
Owning = false;
}
};
-
+
/// \brief Class used to capture the result of searching for an existing
/// declaration of a specific kind and name, along with the ability
/// to update the place where this result was found (the declaration
// The result structure takes care to note that we need to load the
// other declaration chains for this ID.
- return RedeclarableResult(Reader, FirstDeclID);
+ return RedeclarableResult(Reader, FirstDeclID,
+ static_cast<T *>(D)->getKind());
}
/// \brief Attempts to merge the given declaration (D) with another declaration
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
T *First = D->getFirstDeclaration();
if (First->getMostRecentDecl() != First) {
- // There is more than one declaration of this entity, so we will need to
+ assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) &&
+ "Not considered redeclarable?");
+
+ // There is more than one declaration of this entity, so we will need to
// write a redeclaration chain.
Writer.AddDeclRef(First, Record);
Writer.Redeclarations.insert(First);