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@second.h:* {{'kDifferentEnumConstantsValueSecond' from module 'SecondModule' is not present in definition of 'enum DifferentEnumConstants' in module 'FirstModule'}} +// expected-note@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@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@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits