diff options
Diffstat (limited to 'clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 046c699a224..5b86c0a777d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2547,6 +2547,20 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, } } +/// ODR-like semantics for C/ObjC allow us to merge tag types and a structural +/// check in Sema guarantees the types can be merged (see C11 6.2.7/1 or C89 +/// 6.1.2.6/1). Although most merging is done in Sema, we need to guarantee +/// that some types are mergeable during deserialization, otherwise name +/// lookup fails. This is the case for EnumConstantDecl. +bool allowODRLikeMergeInC(NamedDecl *ND) { + if (!ND) + return false; + // TODO: implement merge for other necessary decls. + if (dyn_cast<EnumConstantDecl>(ND)) + return true; + return false; +} + /// \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 @@ -2557,10 +2571,12 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) { if (!Reader.getContext().getLangOpts().Modules) return; - // ODR-based merging is only performed in C++. In C, identically-named things - // in different translation units are not redeclarations (but may still have - // compatible types). - if (!Reader.getContext().getLangOpts().CPlusPlus) + // ODR-based merging is performed in C++ and in some cases (tag types) in C. + // Note that C identically-named things in different translation units are + // not redeclarations, but may still have compatible types, where ODR-like + // semantics may apply. + if (!Reader.getContext().getLangOpts().CPlusPlus && + !allowODRLikeMergeInC(dyn_cast<NamedDecl>(static_cast<T*>(D)))) return; if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) |