This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc31d6b4ef135: [ODRHash] Hash type-as-written (authored by
ChuanqiXu).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D156210/new/
https://reviews.llvm.org/D156210
Files:
clang/lib/AST/ODRHash.cpp
clang/test/Modules/odr_hash-gnu.cpp
clang/test/Modules/odr_hash.cpp
clang/test/Modules/odr_hash.mm
clang/test/Modules/pr63595.cppm
Index: clang/test/Modules/pr63595.cppm
===================================================================
--- /dev/null
+++ clang/test/Modules/pr63595.cppm
@@ -0,0 +1,56 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/module1.cppm -o %t/module1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/module2.cppm -o %t/module2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only
+
+//--- header.h
+namespace NS {
+template <int I>
+class A {
+};
+
+template <template <int I_> class T>
+class B {
+};
+}
+
+//--- module1.h
+namespace NS {
+using C = B<A>;
+}
+struct D : NS::C {
+ using Type = NS::C;
+};
+
+//--- module1.cppm
+// inside NS, using C = B<A>
+module;
+#include "header.h"
+#include "module1.h"
+export module module1;
+export using ::D;
+
+//--- module2.h
+namespace NS {
+using C = B<NS::A>;
+}
+struct D : NS::C {
+ using Type = NS::C;
+};
+
+//--- module2.cppm
+// inside NS, using C = B<NS::A>
+module;
+#include "header.h"
+#include "module2.h"
+export module module2;
+export using ::D;
+
+//--- merge.cpp
+// expected-no-diagnostics
+import module1;
+import module2;
+D d;
Index: clang/test/Modules/odr_hash.mm
===================================================================
--- clang/test/Modules/odr_hash.mm
+++ clang/test/Modules/odr_hash.mm
@@ -112,8 +112,7 @@
// [email protected]:* {{Types::Attributed::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// [email protected]:* {{but in 'FirstModule' found a different body}}
auto function2 = invalid2;
-// [email protected]:* {{'Types::Attributed::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
-// [email protected]:* {{but in 'FirstModule' found a different body}}
+
auto function3 = valid;
#endif
} // namespace Attributed
@@ -266,12 +265,7 @@
}
@end
#else
-// [email protected]:* {{'Interface4::x' from module 'FirstModule' is not present in definition of 'Interface4' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'x' does not match}}
-// [email protected]:* {{'Interface5::y' from module 'FirstModule' is not present in definition of 'Interface5' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'y' does not match}}
-// [email protected]:* {{'Interface6::z' from module 'FirstModule' is not present in definition of 'Interface6' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'z' does not match}}
+
#endif
namespace Types {
@@ -291,14 +285,14 @@
};
#else
Invalid1 i1;
-// [email protected]:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'x' does not match}}
+
Invalid2 i2;
-// [email protected]:* {{'Types::ObjCTypeParam::Invalid2::y' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'y' does not match}}
+
Invalid3 i3;
-// [email protected]:* {{'Types::ObjCTypeParam::Invalid3::z' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'z' does not match}}
+
+// FIXME: We should reject to merge these structs and diagnose for the
+// different definitions for Interface4/Interface5/Interface6.
+
#endif
} // namespace ObjCTypeParam
Index: clang/test/Modules/odr_hash.cpp
===================================================================
--- clang/test/Modules/odr_hash.cpp
+++ clang/test/Modules/odr_hash.cpp
@@ -1046,8 +1046,7 @@
};
#else
S3 s3;
-// [email protected]:* {{'TypeDef::S3::a' from module 'FirstModule' is not present in definition of 'TypeDef::S3' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'a' does not match}}
+// FIXME: We should reject the merge of `S3` due to the inconsistent definition of `T`.
#endif
#if defined(FIRST)
@@ -1172,8 +1171,7 @@
};
#else
S3 s3;
-// [email protected]:* {{'Using::S3::a' from module 'FirstModule' is not present in definition of 'Using::S3' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'a' does not match}}
+// FIXME: We should reject the merge of `S3` due to the inconsistent definition of `T`.
#endif
#if defined(FIRST)
@@ -1361,8 +1359,6 @@
};
#else
S1 s1;
-// [email protected]:* {{'ElaboratedType::S1::x' from module 'FirstModule' is not present in definition of 'ElaboratedType::S1' in module 'SecondModule'}}
-// [email protected]:* {{declaration of 'x' does not match}}
#endif
#define DECLS \
@@ -3616,8 +3612,8 @@
// [email protected]:* {{'Types::Decltype::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// [email protected]:* {{but in 'FirstModule' found a different body}}
auto function2 = invalid2;
-// [email protected]:* {{'Types::Decltype::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
-// [email protected]:* {{but in 'FirstModule' found a different body}}
+// FIXME: We should reject the merge of `invalid2` and diagnose about the
+// inconsistent definition of `global`.
auto function3 = valid;
#endif
} // namespace Decltype
@@ -3700,8 +3696,7 @@
}
#else
auto function1 = invalid1;
-// [email protected]:* {{'Types::DeducedTemplateSpecialization::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
-// [email protected]:* {{but in 'FirstModule' found a different body}}
+// FIXME: We should reject the merge of `invalid1` due to the inconsistent definition.
auto function2 = invalid2;
// [email protected]:* {{'Types::DeducedTemplateSpecialization::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// [email protected]:* {{but in 'FirstModule' found a different body}}
@@ -4946,8 +4941,42 @@
#else
S4 s4;
#endif
+
+#if defined(FIRST)
+namespace NS5 {
+struct T5;
+} // namespace NS5
+class S5 {
+ NS5::T5* t = 0;
+};
+#elif defined(SECOND)
+namespace NS5 {
+typedef struct T5_Other {} T5;
+} // namespace NS4
+class S5 {
+ NS5::T5* t = 0;
+};
+#else
+S5 s5;
+// [email protected]:* {{'TypedefStruct::S5::t' from module 'FirstModule' is not present in definition of 'TypedefStruct::S5' in module 'SecondModule'}}
+// [email protected]:* {{declaration of 't' does not match}}
+#endif
} // namespace TypedefStruct
+#if defined (FIRST)
+typedef int T;
+namespace A {
+ struct X { T n; };
+}
+#elif defined(SECOND)
+namespace A {
+ typedef int T;
+ struct X { T n; };
+}
+#else
+A::X x;
+#endif
+
// Keep macros contained to one file.
#ifdef FIRST
#undef FIRST
Index: clang/test/Modules/odr_hash-gnu.cpp
===================================================================
--- clang/test/Modules/odr_hash-gnu.cpp
+++ clang/test/Modules/odr_hash-gnu.cpp
@@ -65,9 +65,10 @@
// [email protected]:* {{'Types::TypeOfExpr::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof (1 + 2)' (aka 'int')}}
// [email protected]:* {{but in 'SecondModule' found field 'x' with type 'typeof (3)' (aka 'int')}}
Invalid2 i2;
-// [email protected]:* {{'Types::TypeOfExpr::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::TypeOfExpr::Invalid2' in module 'FirstModule'}}
-// [email protected]:* {{declaration of 'x' does not match}}
+
Valid v;
+
+// FIXME: We should diagnose the different definitions of `global`.
#endif
} // namespace TypeOfExpr
@@ -113,8 +114,9 @@
// [email protected]:* {{'Types::TypeOf::Invalid2' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof(int)' (aka 'int')}}
// [email protected]:* {{but in 'SecondModule' found field 'x' with type 'typeof(I)' (aka 'int')}}
Invalid3 i3;
-// [email protected]:* {{'Types::TypeOf::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid3' in module 'FirstModule'}}
-// [email protected]:* {{declaration of 'x' does not match}}
+
+// FIXME: We should reject the `Invalid3` due to the inconsistent definition of `T`.
+
Valid v;
#endif
} // namespace TypeOf
Index: clang/lib/AST/ODRHash.cpp
===================================================================
--- clang/lib/AST/ODRHash.cpp
+++ clang/lib/AST/ODRHash.cpp
@@ -295,9 +295,9 @@
}
void VisitValueDecl(const ValueDecl *D) {
- if (!isa<FunctionDecl>(D)) {
- AddQualType(D->getType());
- }
+ if (auto *DD = dyn_cast<DeclaratorDecl>(D); DD && DD->getTypeSourceInfo())
+ AddQualType(DD->getTypeSourceInfo()->getType());
+
Inherited::VisitValueDecl(D);
}
@@ -351,7 +351,7 @@
void VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
ID.AddInteger(D->getPropertyAttributes());
ID.AddInteger(D->getPropertyImplementation());
- AddQualType(D->getType());
+ AddQualType(D->getTypeSourceInfo()->getType());
AddDecl(D);
Inherited::VisitObjCPropertyDecl(D);
@@ -394,7 +394,9 @@
AddDecl(Method);
- AddQualType(Method->getReturnType());
+ if (Method->getReturnTypeSourceInfo())
+ AddQualType(Method->getReturnTypeSourceInfo()->getType());
+
ID.AddInteger(Method->param_size());
for (auto Param : Method->parameters())
Hash.AddSubDecl(Param);
@@ -593,7 +595,7 @@
ID.AddInteger(Record->getNumBases());
auto Bases = Record->bases();
for (const auto &Base : Bases) {
- AddQualType(Base.getType());
+ AddQualType(Base.getTypeSourceInfo()->getType());
ID.AddInteger(Base.isVirtual());
ID.AddInteger(Base.getAccessSpecifierAsWritten());
}
@@ -912,29 +914,7 @@
void VisitType(const Type *T) {}
void VisitAdjustedType(const AdjustedType *T) {
- QualType Original = T->getOriginalType();
- QualType Adjusted = T->getAdjustedType();
-
- // The original type and pointee type can be the same, as in the case of
- // function pointers decaying to themselves. Set a bool and only process
- // the type once, to prevent doubling the work.
- SplitQualType split = Adjusted.split();
- if (auto Pointer = dyn_cast<PointerType>(split.Ty)) {
- if (Pointer->getPointeeType() == Original) {
- Hash.AddBoolean(true);
- ID.AddInteger(split.Quals.getAsOpaqueValue());
- AddQualType(Original);
- VisitType(T);
- return;
- }
- }
-
- // The original type and pointee type are different, such as in the case
- // of a array decaying to an element pointer. Set a bool to false and
- // process both types.
- Hash.AddBoolean(false);
- AddQualType(Original);
- AddQualType(Adjusted);
+ AddQualType(T->getOriginalType());
VisitType(T);
}
@@ -973,7 +953,6 @@
void VisitAttributedType(const AttributedType *T) {
ID.AddInteger(T->getAttrKind());
AddQualType(T->getModifiedType());
- AddQualType(T->getEquivalentType());
VisitType(T);
}
@@ -995,7 +974,6 @@
void VisitDecltypeType(const DecltypeType *T) {
AddStmt(T->getUnderlyingExpr());
- AddQualType(T->getUnderlyingType());
VisitType(T);
}
@@ -1184,31 +1162,12 @@
void VisitTypedefType(const TypedefType *T) {
AddDecl(T->getDecl());
- QualType UnderlyingType = T->getDecl()->getUnderlyingType();
- VisitQualifiers(UnderlyingType.getQualifiers());
- while (true) {
- if (const TypedefType *Underlying =
- dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
- UnderlyingType = Underlying->getDecl()->getUnderlyingType();
- continue;
- }
- if (const ElaboratedType *Underlying =
- dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) {
- UnderlyingType = Underlying->getNamedType();
- continue;
- }
-
- break;
- }
- AddType(UnderlyingType.getTypePtr());
VisitType(T);
}
void VisitTypeOfExprType(const TypeOfExprType *T) {
AddStmt(T->getUnderlyingExpr());
Hash.AddBoolean(T->isSugared());
- if (T->isSugared())
- AddQualType(T->desugar());
VisitType(T);
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits