diff clang/test/Modules/compare-record.c @ 252:1f2b6ac9f198 llvm-original

LLVM16-1
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 18 Aug 2023 09:04:13 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clang/test/Modules/compare-record.c	Fri Aug 18 09:04:13 2023 +0900
@@ -0,0 +1,501 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/include/first.h
+// RUN: cat %t/test.c        >> %t/include/first.h
+// RUN: echo "#undef FIRST"  >> %t/include/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/include/second.h
+// RUN: cat %t/test.c         >> %t/include/second.h
+// RUN: echo "#undef SECOND"  >> %t/include/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x objective-c %t/include/first.h -fblocks -fobjc-arc
+// RUN: %clang_cc1 -fsyntax-only -x objective-c %t/include/second.h -fblocks -fobjc-arc
+
+// Run test
+// RUN: %clang_cc1 -I%t/include -verify %t/test.c -fblocks -fobjc-arc \
+// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
+
+// Run tests for nested structs
+// DEFINE: %{filename} = test-nested-struct.c
+// DEFINE: %{macro_flag} = -DCASE1=1
+// DEFINE: %{command} = %clang_cc1 -I%t/include -verify %t/%{filename} -fblocks -fobjc-arc \
+// DEFINE:             -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache \
+// DEFINE:             %{macro_flag} -emit-llvm -o %t/%{filename}.bc
+// RUN: %{command}
+// REDEFINE: %{macro_flag} = -DCASE2=1
+// RUN: %{command}
+// REDEFINE: %{macro_flag} = -DCASE3=1
+// RUN: %{command}
+
+// Run tests for anonymous nested structs and unions
+// REDEFINE: %{filename} = test-anonymous.c
+// REDEFINE: %{macro_flag} = -DCASE1=1
+// RUN: %{command}
+// REDEFINE: %{macro_flag} = -DCASE2=1
+// RUN: %{command}
+// REDEFINE: %{macro_flag} = -DCASE3=1
+// RUN: %{command}
+
+// Test that we don't accept different structs and unions with the same name
+// from multiple modules but detect mismatches and provide actionable
+// diagnostic.
+
+//--- include/first-empty.h
+//--- include/module.modulemap
+module First {
+  module Empty {
+    header "first-empty.h"
+  }
+  module Hidden {
+    header "first.h"
+    header "first-nested-struct.h"
+    header "first-anonymous.h"
+    export *
+  }
+}
+module Second {
+  header "second.h"
+  header "second-nested-struct.h"
+  header "second-anonymous.h"
+  export *
+}
+
+//--- test.c
+#if !defined(FIRST) && !defined(SECOND)
+# include "first-empty.h"
+# include "second.h"
+#endif
+
+#if defined(FIRST)
+struct CompareForwardDeclaration1;
+struct CompareForwardDeclaration2 {};
+#elif defined(SECOND)
+struct CompareForwardDeclaration1 {};
+struct CompareForwardDeclaration2;
+#else
+struct CompareForwardDeclaration1 *compareForwardDeclaration1;
+struct CompareForwardDeclaration2 *compareForwardDeclaration2;
+#endif
+
+#if defined(FIRST)
+struct CompareMatchingFields {
+  int matchingFieldName;
+};
+
+struct CompareFieldPresence1 {
+  int fieldPresence1;
+};
+struct CompareFieldPresence2 {};
+
+struct CompareFieldName {
+  int fieldNameA;
+};
+
+struct CompareFieldOrder {
+  int fieldOrderX;
+  int fieldOrderY;
+};
+#elif defined(SECOND)
+struct CompareMatchingFields {
+  int matchingFieldName;
+};
+
+struct CompareFieldPresence1 {
+};
+struct CompareFieldPresence2 {
+  int fieldPresence2;
+};
+
+struct CompareFieldName {
+  int fieldNameB;
+};
+
+struct CompareFieldOrder {
+  int fieldOrderY;
+  int fieldOrderX;
+};
+#else
+struct CompareMatchingFields compareMatchingFields;
+struct CompareFieldPresence1 compareFieldPresence1;
+// expected-error@first.h:* {{'CompareFieldPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field}}
+// expected-note@second.h:* {{but in 'Second' found end of class}}
+struct CompareFieldPresence2 compareFieldPresence2;
+// expected-error@second.h:* {{'CompareFieldPresence2::fieldPresence2' from module 'Second' is not present in definition of 'struct CompareFieldPresence2' in module 'First.Hidden'}}
+// expected-note@first.h:* {{definition has no member 'fieldPresence2'}}
+struct CompareFieldName compareFieldName;
+// expected-error@second.h:* {{'CompareFieldName::fieldNameB' from module 'Second' is not present in definition of 'struct CompareFieldName' in module 'First.Hidden'}}
+// expected-note@first.h:* {{definition has no member 'fieldNameB'}}
+struct CompareFieldOrder compareFieldOrder;
+// expected-error@first.h:* {{'CompareFieldOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'fieldOrderX'}}
+// expected-note@second.h:* {{but in 'Second' found field 'fieldOrderY'}}
+#endif
+
+#if defined(FIRST)
+struct CompareFieldType {
+  int fieldType;
+};
+
+typedef int FieldTypedefNameA;
+struct CompareFieldTypedefName {
+  FieldTypedefNameA fieldTypedefName;
+};
+
+typedef int TypedefUnderlyingType;
+struct CompareFieldTypeUnderlyingTypedef {
+  TypedefUnderlyingType fieldTypeUnderlyingTypedef;
+};
+
+typedef int TypedefFinal;
+struct CompareFieldTypedefChain {
+  TypedefFinal fieldTypeTypedefChain;
+};
+#elif defined(SECOND)
+struct CompareFieldType {
+  float fieldType;
+};
+
+typedef int FieldTypedefNameB;
+struct CompareFieldTypedefName {
+  FieldTypedefNameB fieldTypedefName;
+};
+
+struct CompareFieldTypeUnderlyingTypedef {
+  int fieldTypeUnderlyingTypedef;
+};
+
+typedef int TypedefIntermediate;
+typedef TypedefIntermediate TypedefFinal;
+struct CompareFieldTypedefChain {
+  TypedefFinal fieldTypeTypedefChain;
+};
+#else
+struct CompareFieldType compareFieldType;
+// expected-error@second.h:* {{'CompareFieldType::fieldType' from module 'Second' is not present in definition of 'struct CompareFieldType' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'fieldType' does not match}}
+struct CompareFieldTypedefName compareFieldTypedefName;
+// expected-error@first.h:* {{'CompareFieldTypedefName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'fieldTypedefName' with type 'FieldTypedefNameA' (aka 'int')}}
+// expected-note@second.h:* {{but in 'Second' found field 'fieldTypedefName' with type 'FieldTypedefNameB' (aka 'int')}}
+struct CompareFieldTypeUnderlyingTypedef compareFieldTypeUnderlyingTypedef;
+// expected-error@first.h:* {{'CompareFieldTypeUnderlyingTypedef' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'fieldTypeUnderlyingTypedef' with type 'TypedefUnderlyingType' (aka 'int')}}
+// expected-note@second.h:* {{but in 'Second' found field 'fieldTypeUnderlyingTypedef' with type 'int'}}
+struct CompareFieldTypedefChain compareFieldTypedefChain;
+#endif
+
+#if defined(FIRST)
+struct CompareMatchingBitfields {
+  unsigned matchingBitfields : 3;
+};
+
+struct CompareBitfieldPresence1 {
+  unsigned bitfieldPresence1 : 1;
+};
+struct CompareBitfieldPresence2 {
+  unsigned bitfieldPresence2;
+};
+
+struct CompareBitfieldWidth {
+  unsigned bitfieldWidth : 2;
+};
+
+struct CompareBitfieldWidthExpression {
+  unsigned bitfieldWidthExpression : 1 + 1;
+};
+#elif defined(SECOND)
+struct CompareMatchingBitfields {
+  unsigned matchingBitfields : 3;
+};
+
+struct CompareBitfieldPresence1 {
+  unsigned bitfieldPresence1;
+};
+struct CompareBitfieldPresence2 {
+  unsigned bitfieldPresence2 : 1;
+};
+
+struct CompareBitfieldWidth {
+  unsigned bitfieldWidth : 1;
+};
+
+struct CompareBitfieldWidthExpression {
+  unsigned bitfieldWidthExpression : 2;
+};
+#else
+struct CompareMatchingBitfields compareMatchingBitfields;
+struct CompareBitfieldPresence1 compareBitfieldPresence1;
+// expected-error@first.h:* {{'CompareBitfieldPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found bitfield 'bitfieldPresence1'}}
+// expected-note@second.h:* {{but in 'Second' found non-bitfield 'bitfieldPresence1'}}
+struct CompareBitfieldPresence2 compareBitfieldPresence2;
+// expected-error@first.h:* {{'CompareBitfieldPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found non-bitfield 'bitfieldPresence2'}}
+// expected-note@second.h:* {{but in 'Second' found bitfield 'bitfieldPresence2'}}
+struct CompareBitfieldWidth compareBitfieldWidth;
+// expected-error@first.h:* {{'CompareBitfieldWidth' has different definitions in different modules; first difference is definition in module 'First.Hidden' found bitfield 'bitfieldWidth' with one width expression}}
+// expected-note@second.h:* {{but in 'Second' found bitfield 'bitfieldWidth' with different width expression}}
+struct CompareBitfieldWidthExpression compareBitfieldWidthExpression;
+// expected-error@first.h:* {{'CompareBitfieldWidthExpression' has different definitions in different modules; first difference is definition in module 'First.Hidden' found bitfield 'bitfieldWidthExpression' with one width expression}}
+// expected-note@second.h:* {{but in 'Second' found bitfield 'bitfieldWidthExpression' with different width expressio}}
+#endif
+
+#if defined(FIRST)
+struct CompareMatchingArrayFields {
+  int matchingArrayField[7];
+};
+
+struct CompareArrayLength {
+  int arrayLengthField[5];
+};
+
+struct CompareArrayType {
+  int arrayTypeField[5];
+};
+#elif defined(SECOND)
+struct CompareMatchingArrayFields {
+  int matchingArrayField[7];
+};
+
+struct CompareArrayLength {
+  int arrayLengthField[7];
+};
+
+struct CompareArrayType {
+  float arrayTypeField[5];
+};
+#else
+struct CompareMatchingArrayFields compareMatchingArrayFields;
+struct CompareArrayLength compareArrayLength;
+// expected-error@second.h:* {{'CompareArrayLength::arrayLengthField' from module 'Second' is not present in definition of 'struct CompareArrayLength' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'arrayLengthField' does not match}}
+struct CompareArrayType compareArrayType;
+// expected-error@second.h:* {{'CompareArrayType::arrayTypeField' from module 'Second' is not present in definition of 'struct CompareArrayType' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'arrayTypeField' does not match}}
+#endif
+
+#if defined(FIRST)
+struct CompareFieldAsForwardDeclaration {
+  struct FieldForwardDeclaration *fieldForwardDeclaration;
+};
+
+enum FieldEnumA { kFieldEnumValue };
+struct CompareFieldAsEnum {
+  enum FieldEnumA fieldEnum;
+};
+
+struct FieldStructA {};
+struct CompareFieldAsStruct {
+  struct FieldStructA fieldStruct;
+};
+#elif defined(SECOND)
+struct FieldForwardDeclaration {};
+struct CompareFieldAsForwardDeclaration {
+  struct FieldForwardDeclaration *fieldForwardDeclaration;
+};
+
+enum FieldEnumB { kFieldEnumValue };
+struct CompareFieldAsEnum {
+  enum FieldEnumB fieldEnum;
+};
+
+struct FieldStructB {};
+struct CompareFieldAsStruct {
+  struct FieldStructB fieldStruct;
+};
+#else
+struct CompareFieldAsForwardDeclaration compareFieldAsForwardDeclaration;
+struct CompareFieldAsEnum compareFieldAsEnum;
+// expected-error@second.h:* {{'CompareFieldAsEnum::fieldEnum' from module 'Second' is not present in definition of 'struct CompareFieldAsEnum' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'fieldEnum' does not match}}
+struct CompareFieldAsStruct compareFieldAsStruct;
+// expected-error@second.h:* {{'CompareFieldAsStruct::fieldStruct' from module 'Second' is not present in definition of 'struct CompareFieldAsStruct' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'fieldStruct' does not match}}
+#endif
+
+#if defined(FIRST)
+union CompareMatchingUnionFields {
+  int matchingFieldA;
+  float matchingFieldB;
+};
+
+union CompareUnionFieldOrder {
+  int unionFieldOrderA;
+  float unionFieldOrderB;
+};
+
+union CompareUnionFieldType {
+  int unionFieldType;
+};
+#elif defined(SECOND)
+union CompareMatchingUnionFields {
+  int matchingFieldA;
+  float matchingFieldB;
+};
+
+union CompareUnionFieldOrder {
+  float unionFieldOrderB;
+  int unionFieldOrderA;
+};
+
+union CompareUnionFieldType {
+  unsigned int unionFieldType;
+};
+#else
+union CompareMatchingUnionFields compareMatchingUnionFields;
+union CompareUnionFieldOrder compareUnionFieldOrder;
+// expected-error@first.h:* {{'CompareUnionFieldOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'unionFieldOrderA'}}
+// expected-note@second.h:* {{but in 'Second' found field 'unionFieldOrderB'}}
+union CompareUnionFieldType compareUnionFieldType;
+// expected-error@second.h:* {{'CompareUnionFieldType::unionFieldType' from module 'Second' is not present in definition of 'union CompareUnionFieldType' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'unionFieldType' does not match}}
+#endif
+
+// Test that we find and compare definitions even if they are not the first encountered declaration in a module.
+#if defined(FIRST)
+struct CompareDefinitionsRegardlessForwardDeclarations {
+  int definitionField;
+};
+#elif defined(SECOND)
+struct CompareDefinitionsRegardlessForwardDeclarations;
+struct CompareDefinitionsRegardlessForwardDeclarations {
+  float definitionField;
+};
+#else
+struct CompareDefinitionsRegardlessForwardDeclarations compareDefinitions;
+// expected-error@second.h:* {{'CompareDefinitionsRegardlessForwardDeclarations::definitionField' from module 'Second' is not present in definition of 'struct CompareDefinitionsRegardlessForwardDeclarations' in module 'First.Hidden'}}
+// expected-note@first.h:* {{declaration of 'definitionField' does not match}}
+#endif
+
+//--- include/first-nested-struct.h
+struct CompareNestedStruct {
+  struct NestedLevel1 {
+    struct NestedLevel2 {
+      int a;
+    } y;
+  } x;
+};
+
+struct IndirectStruct {
+  int mismatchingField;
+};
+struct DirectStruct {
+  struct IndirectStruct indirectField;
+};
+struct CompareDifferentFieldInIndirectStruct {
+  struct DirectStruct directField;
+};
+struct CompareIndirectStructPointer {
+  struct DirectStruct *directFieldPointer;
+};
+
+//--- include/second-nested-struct.h
+struct CompareNestedStruct {
+  struct NestedLevel1 {
+    struct NestedLevel2 {
+      float b;
+    } y;
+  } x;
+};
+
+struct IndirectStruct {
+  float mismatchingField;
+};
+struct DirectStruct {
+  struct IndirectStruct indirectField;
+};
+struct CompareDifferentFieldInIndirectStruct {
+  struct DirectStruct directField;
+};
+struct CompareIndirectStructPointer {
+  struct DirectStruct *directFieldPointer;
+};
+
+//--- test-nested-struct.c
+#include "first-empty.h"
+#include "second-nested-struct.h"
+
+#if defined(CASE1)
+struct CompareNestedStruct compareNestedStruct;
+// expected-error@second-nested-struct.h:* {{'NestedLevel2::b' from module 'Second' is not present in definition of 'struct NestedLevel2' in module 'First.Hidden'}}
+// expected-note@first-nested-struct.h:* {{definition has no member 'b'}}
+#elif defined(CASE2)
+struct CompareDifferentFieldInIndirectStruct compareIndirectStruct;
+// expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}}
+// expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}}
+#elif defined(CASE3)
+// expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}}
+// expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}}
+struct CompareIndirectStructPointer compareIndirectStructPointer;
+struct DirectStruct test() {
+  // Make sure the type behind the pointer is inspected.
+  return *compareIndirectStructPointer.directFieldPointer;
+}
+#endif
+
+//--- include/first-anonymous.h
+struct CompareAnonymousNestedUnion {
+  union {
+    int anonymousNestedUnionField;
+  };
+};
+
+struct CompareAnonymousNestedStruct {
+  struct {
+    int anonymousNestedStructField;
+  };
+};
+
+struct CompareDeeplyNestedAnonymousUnionsAndStructs {
+  union {
+    int x;
+    union {
+      int y;
+      struct {
+        int z;
+      };
+    };
+  };
+};
+
+//--- include/second-anonymous.h
+struct CompareAnonymousNestedUnion {
+  union {
+    float anonymousNestedUnionField;
+  };
+};
+
+struct CompareAnonymousNestedStruct {
+  struct {
+    float anonymousNestedStructField;
+  };
+};
+
+struct CompareDeeplyNestedAnonymousUnionsAndStructs {
+  union {
+    int x;
+    union {
+      int y;
+      struct {
+        float z;
+      };
+    };
+  };
+};
+
+//--- test-anonymous.c
+#include "first-empty.h"
+#include "second-anonymous.h"
+
+#if defined(CASE1)
+struct CompareAnonymousNestedUnion compareAnonymousNestedUnion;
+// expected-error-re@second-anonymous.h:* {{'CompareAnonymousNestedUnion::(anonymous union)::anonymousNestedUnionField' from module 'Second' is not present in definition of 'union CompareAnonymousNestedUnion::(anonymous at {{.*}})' in module 'First.Hidden'}}
+// expected-note@first-anonymous.h:* {{declaration of 'anonymousNestedUnionField' does not match}}
+#elif defined(CASE2)
+struct CompareAnonymousNestedStruct compareAnonymousNestedStruct;
+// expected-error-re@second-anonymous.h:* {{'CompareAnonymousNestedStruct::(anonymous struct)::anonymousNestedStructField' from module 'Second' is not present in definition of 'struct CompareAnonymousNestedStruct::(anonymous at {{.*}})' in module 'First.Hidden'}}
+// expected-note@first-anonymous.h:* {{declaration of 'anonymousNestedStructField' does not match}}
+#elif defined(CASE3)
+struct CompareDeeplyNestedAnonymousUnionsAndStructs compareDeeplyNested;
+// expected-error-re@second-anonymous.h:* {{'CompareDeeplyNestedAnonymousUnionsAndStructs::(anonymous union)::(anonymous union)::(anonymous struct)::z' from module 'Second' is not present in definition of 'struct CompareDeeplyNestedAnonymousUnionsAndStructs::(anonymous at {{.*}})' in module 'First.Hidden'}}
+// expected-note@first-anonymous.h:* {{declaration of 'z' does not match}}
+#endif