summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp24
-rw-r--r--clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a.h1
-rw-r--r--clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Headers/a0.h1
-rw-r--r--clang/test/Modules/Inputs/non-ambiguous-enum/A.framework/Modules/module.modulemap6
-rw-r--r--clang/test/Modules/Inputs/non-ambiguous-enum/B.framework/Headers/b.h6
-rw-r--r--clang/test/Modules/non-ambiguous-enum.m10
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;
+}
OpenPOWER on IntegriCloud