diff options
6 files changed, 44 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))) diff --git a/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h b/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h new file mode 100644 index 00000000000..060bc499738 --- /dev/null +++ b/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h @@ -0,0 +1 @@ +#include <A/a0.h> diff --git a/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h b/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h new file mode 100644 index 00000000000..2e4d0912119 --- /dev/null +++ b/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h @@ -0,0 +1 @@ +#include <B/b.h> diff --git a/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap new file mode 100644 index 00000000000..d9a1981d53c --- /dev/null +++ b/clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap @@ -0,0 +1,6 @@ + +framework module A { +  header "a.h" +  //module * { export * } +  export * +} diff --git a/clang/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h b/clang/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h new file mode 100644 index 00000000000..def44e3a634 --- /dev/null +++ b/clang/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h @@ -0,0 +1,6 @@ +typedef long NSInteger; +typedef enum __attribute__((flag_enum,enum_extensibility(open))) MyObjCEnum : NSInteger MyObjCEnum; + +enum MyObjCEnum : NSInteger { +    MyEnumCst = 1, +} __attribute__((availability(ios,introduced=11.0))) __attribute__((availability(tvos,unavailable))) ; diff --git a/clang/test/Modules/non-ambiguous-enum.m b/clang/test/Modules/non-ambiguous-enum.m new file mode 100644 index 00000000000..f6d2a3ecb6d --- /dev/null +++ b/clang/test/Modules/non-ambiguous-enum.m @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/non-ambiguous-enum -fsyntax-only %s -verify +#import <B/B.h> +#import <A/A.h> + +// expected-no-diagnostics + +int foo() { +  return MyEnumCst; +}  | 

