[clang] 6d7d8e5 - [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (#90298)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 2 18:10:40 PDT 2024
Author: Volodymyr Sapsai
Date: 2024-05-02T18:10:36-07:00
New Revision: 6d7d8e5b59cb0a66765ccf657814ae6039e27931
URL: https://github.com/llvm/llvm-project/commit/6d7d8e5b59cb0a66765ccf657814ae6039e27931
DIFF: https://github.com/llvm/llvm-project/commit/6d7d8e5b59cb0a66765ccf657814ae6039e27931.diff
LOG: [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (#90298)
There is no reason for C and Objective-C to differ from C++ in this
matter.
rdar://85531830
Added:
clang/test/Modules/odr_hash-enum.c
Modified:
clang/lib/Serialization/ASTReaderDecl.cpp
Removed:
################################################################################
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 744f11de88c2f8..6afbbfe20f26b7 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -805,9 +805,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
// If this is a definition subject to the ODR, and we already have a
// definition, merge this one into it.
- if (ED->isCompleteDefinition() &&
- Reader.getContext().getLangOpts().Modules &&
- Reader.getContext().getLangOpts().CPlusPlus) {
+ if (ED->isCompleteDefinition() && Reader.getContext().getLangOpts().Modules) {
EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
if (!OldDef) {
// This is the first time we've seen an imported definition. Look for a
@@ -3304,8 +3302,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
return RD->getDefinition();
if (auto *ED = dyn_cast<EnumDecl>(DC))
- return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
- : nullptr;
+ return ED->getDefinition();
if (auto *OID = dyn_cast<ObjCInterfaceDecl>(DC))
return OID->getDefinition();
diff --git a/clang/test/Modules/odr_hash-enum.c b/clang/test/Modules/odr_hash-enum.c
new file mode 100644
index 00000000000000..f8ede923fe2caa
--- /dev/null
+++ b/clang/test/Modules/odr_hash-enum.c
@@ -0,0 +1,75 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c %t/Inputs/first.h
+// RUN: %clang_cc1 -fsyntax-only -x c %t/Inputs/second.h
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.modulemap
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.modulemap
+// RUN: echo "}" >> %t/Inputs/module.modulemap
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.modulemap
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.modulemap
+// RUN: echo "}" >> %t/Inputs/module.modulemap
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c -I%t/Inputs -verify %s
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+#if defined(FIRST)
+enum DifferentEnumConstants { kDifferentEnumConstantsValueFirst };
+#elif defined(SECOND)
+enum DifferentEnumConstants { kDifferentEnumConstantsValueSecond };
+#else
+enum DifferentEnumConstants
diff erentEnumConstants;
+// expected-error at second.h:* {{'kDifferentEnumConstantsValueSecond' from module 'SecondModule' is not present in definition of 'enum DifferentEnumConstants' in module 'FirstModule'}}
+// expected-note at first.h:* {{definition has no member 'kDifferentEnumConstantsValueSecond'}}
+#endif
+
+#if defined(FIRST)
+enum DifferentEnumValues { kDifferentEnumValue = 0 };
+#elif defined(SECOND)
+enum DifferentEnumValues { kDifferentEnumValue = 1 };
+#else
+enum DifferentEnumValues
diff erentEnumValue;
+// expected-error at first.h:* {{'DifferentEnumValues' has
diff erent definitions in
diff erent modules; definition in module 'FirstModule' first
diff erence is 1st element 'kDifferentEnumValue' has an initializer}}
+// expected-note at second.h:* {{but in 'SecondModule' found 1st element 'kDifferentEnumValue' has
diff erent initializer}}
+#endif
+
+#if defined(FIRST)
+enum {
+ kAnonymousEnumValueFirst = 1,
+};
+#elif defined(SECOND)
+enum {
+ kAnonymousEnumValueSecond = 2,
+};
+#else
+// Anonymous enums don't have to match, no errors expected.
+int anonymousEnumValue = kAnonymousEnumValueFirst + kAnonymousEnumValueSecond;
+#endif
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
More information about the cfe-commits
mailing list