<div dir="ltr"><div dir="ltr">Galina,<div><br></div><div>Thank you for letting me know.  The test case used an enum with default type which has different behavior on Window systems.  I've added a triple in r341496 which should fix the test.</div><div><br></div><div>Richard</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 5, 2018 at 1:45 PM Galina Kistanova <<a href="mailto:gkistanova@gmail.com">gkistanova@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr">Hello Richard,<br><br>This commit added broken test to one of our builders:<br><a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/12240" target="_blank">http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/12240</a><br><br>. . .<br>Failing Tests (3):<br>    Clang :: Modules/odr_hash.cpp<br>    LLVM :: CodeGen/AMDGPU/mubuf-legalize-operands.ll<br>    LLVM :: CodeGen/AMDGPU/mubuf-legalize-operands.mir<br><br>Please have a look?<br>The builder was already red and did not send notifications on this.<br><br>Thanks<br><br>Galina<br></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Sep 4, 2018 at 3:54 PM Richard Trieu via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rtrieu<br>
Date: Tue Sep  4 15:53:19 2018<br>
New Revision: 341421<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=341421&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=341421&view=rev</a><br>
Log:<br>
[ODRHash] Extend hash to support all Type's.<br>
<br>
Added:<br>
    cfe/trunk/test/Modules/odr_hash-gnu.cpp<br>
    cfe/trunk/test/Modules/odr_hash-vector.cpp<br>
    cfe/trunk/test/Modules/<a href="http://odr_hash.cl" rel="noreferrer" target="_blank">odr_hash.cl</a><br>
Modified:<br>
    cfe/trunk/include/clang/AST/ODRHash.h<br>
    cfe/trunk/lib/AST/ODRHash.cpp<br>
    cfe/trunk/lib/AST/StmtProfile.cpp<br>
    cfe/trunk/test/Modules/odr_hash-blocks.cpp<br>
    cfe/trunk/test/Modules/odr_hash.cpp<br>
    cfe/trunk/test/Modules/<a href="http://odr_hash.mm" rel="noreferrer" target="_blank">odr_hash.mm</a><br>
<br>
Modified: cfe/trunk/include/clang/AST/ODRHash.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ODRHash.h?rev=341421&r1=341420&r2=341421&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ODRHash.h?rev=341421&r1=341420&r2=341421&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ODRHash.h (original)<br>
+++ cfe/trunk/include/clang/AST/ODRHash.h Tue Sep  4 15:53:19 2018<br>
@@ -83,7 +83,7 @@ public:<br>
   void AddIdentifierInfo(const IdentifierInfo *II);<br>
   void AddNestedNameSpecifier(const NestedNameSpecifier *NNS);<br>
   void AddTemplateName(TemplateName Name);<br>
-  void AddDeclarationName(DeclarationName Name);<br>
+  void AddDeclarationName(DeclarationName Name, bool TreatAsDecl = false);<br>
   void AddTemplateArgument(TemplateArgument TA);<br>
   void AddTemplateParameterList(const TemplateParameterList *TPL);<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ODRHash.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=341421&r1=341420&r2=341421&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=341421&r1=341420&r2=341421&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ODRHash.cpp (original)<br>
+++ cfe/trunk/lib/AST/ODRHash.cpp Tue Sep  4 15:53:19 2018<br>
@@ -32,7 +32,10 @@ void ODRHash::AddIdentifierInfo(const Id<br>
   ID.AddString(II->getName());<br>
 }<br>
<br>
-void ODRHash::AddDeclarationName(DeclarationName Name) {<br>
+void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) {<br>
+  if (TreatAsDecl)<br>
+    AddBoolean(true);<br>
+<br>
   // Index all DeclarationName and use index numbers to refer to them.<br>
   auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));<br>
   ID.AddInteger(Result.first->second);<br>
@@ -88,6 +91,9 @@ void ODRHash::AddDeclarationName(Declara<br>
     }<br>
   }<br>
   }<br>
+<br>
+  if (TreatAsDecl)<br>
+    AddBoolean(false);<br>
 }<br>
<br>
 void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {<br>
@@ -405,6 +411,7 @@ public:<br>
<br>
   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {<br>
     AddDecl(D->getTemplatedDecl());<br>
+    ID.AddInteger(D->getTemplatedDecl()->getODRHash());<br>
     Inherited::VisitFunctionTemplateDecl(D);<br>
   }<br>
<br>
@@ -552,11 +559,27 @@ void ODRHash::AddFunctionDecl(const Func<br>
                        !Function->isDefaulted() && !Function->isDeleted() &&<br>
                        !Function->isLateTemplateParsed();<br>
   AddBoolean(HasBody);<br>
-  if (HasBody) {<br>
-    auto *Body = Function->getBody();<br>
-    AddBoolean(Body);<br>
-    if (Body)<br>
-      AddStmt(Body);<br>
+  if (!HasBody) {<br>
+    return;<br>
+  }<br>
+<br>
+  auto *Body = Function->getBody();<br>
+  AddBoolean(Body);<br>
+  if (Body)<br>
+    AddStmt(Body);<br>
+<br>
+  // Filter out sub-Decls which will not be processed in order to get an<br>
+  // accurate count of Decl's.<br>
+  llvm::SmallVector<const Decl *, 16> Decls;<br>
+  for (Decl *SubDecl : Function->decls()) {<br>
+    if (isWhitelistedDecl(SubDecl, Function)) {<br>
+      Decls.push_back(SubDecl);<br>
+    }<br>
+  }<br>
+<br>
+  ID.AddInteger(Decls.size());<br>
+  for (auto SubDecl : Decls) {<br>
+    AddSubDecl(SubDecl);<br>
   }<br>
 }<br>
<br>
@@ -592,13 +615,24 @@ void ODRHash::AddDecl(const Decl *D) {<br>
   assert(D && "Expecting non-null pointer.");<br>
   D = D->getCanonicalDecl();<br>
<br>
-  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {<br>
-    AddDeclarationName(ND->getDeclName());<br>
+  const NamedDecl *ND = dyn_cast<NamedDecl>(D);<br>
+  AddBoolean(ND);<br>
+  if (!ND) {<br>
+    ID.AddInteger(D->getKind());<br>
     return;<br>
   }<br>
<br>
-  ID.AddInteger(D->getKind());<br>
-  // TODO: Handle non-NamedDecl here.<br>
+  AddDeclarationName(ND->getDeclName());<br>
+<br>
+  const auto *Specialization =<br>
+            dyn_cast<ClassTemplateSpecializationDecl>(D);<br>
+  AddBoolean(Specialization);<br>
+  if (Specialization) {<br>
+    const TemplateArgumentList &List = Specialization->getTemplateArgs();<br>
+    ID.AddInteger(List.size());<br>
+    for (const TemplateArgument &TA : List.asArray())<br>
+      AddTemplateArgument(TA);<br>
+  }<br>
 }<br>
<br>
 namespace {<br>
@@ -700,11 +734,67 @@ public:<br>
     VisitArrayType(T);<br>
   }<br>
<br>
+  void VisitAttributedType(const AttributedType *T) {<br>
+    ID.AddInteger(T->getAttrKind());<br>
+    AddQualType(T->getModifiedType());<br>
+    AddQualType(T->getEquivalentType());<br>
+<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitBlockPointerType(const BlockPointerType *T) {<br>
+    AddQualType(T->getPointeeType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
   void VisitBuiltinType(const BuiltinType *T) {<br>
     ID.AddInteger(T->getKind());<br>
     VisitType(T);<br>
   }<br>
<br>
+  void VisitComplexType(const ComplexType *T) {<br>
+    AddQualType(T->getElementType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitDecltypeType(const DecltypeType *T) {<br>
+    AddStmt(T->getUnderlyingExpr());<br>
+    AddQualType(T->getUnderlyingType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitDependentDecltypeType(const DependentDecltypeType *T) {<br>
+    VisitDecltypeType(T);<br>
+  }<br>
+<br>
+  void VisitDeducedType(const DeducedType *T) {<br>
+    AddQualType(T->getDeducedType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitAutoType(const AutoType *T) {<br>
+    ID.AddInteger((unsigned)T->getKeyword());<br>
+    VisitDeducedType(T);<br>
+  }<br>
+<br>
+  void VisitDeducedTemplateSpecializationType(<br>
+      const DeducedTemplateSpecializationType *T) {<br>
+    Hash.AddTemplateName(T->getTemplateName());<br>
+    VisitDeducedType(T);<br>
+  }<br>
+<br>
+  void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) {<br>
+    AddQualType(T->getPointeeType());<br>
+    AddStmt(T->getAddrSpaceExpr());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {<br>
+    AddQualType(T->getElementType());<br>
+    AddStmt(T->getSizeExpr());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
   void VisitFunctionType(const FunctionType *T) {<br>
     AddQualType(T->getReturnType());<br>
     T->getExtInfo().Profile(ID);<br>
@@ -726,6 +816,74 @@ public:<br>
     VisitFunctionType(T);<br>
   }<br>
<br>
+  void VisitInjectedClassNameType(const InjectedClassNameType *T) {<br>
+    AddDecl(T->getDecl());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitMemberPointerType(const MemberPointerType *T) {<br>
+    AddQualType(T->getPointeeType());<br>
+    AddType(T->getClass());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {<br>
+    AddQualType(T->getPointeeType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitObjCObjectType(const ObjCObjectType *T) {<br>
+    AddDecl(T->getInterface());<br>
+<br>
+    auto TypeArgs = T->getTypeArgsAsWritten();<br>
+    ID.AddInteger(TypeArgs.size());<br>
+    for (auto Arg : TypeArgs) {<br>
+      AddQualType(Arg);<br>
+    }<br>
+<br>
+    auto Protocols = T->getProtocols();<br>
+    ID.AddInteger(Protocols.size());<br>
+    for (auto Protocol : Protocols) {<br>
+      AddDecl(Protocol);<br>
+    }<br>
+<br>
+    Hash.AddBoolean(T->isKindOfType());<br>
+<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitObjCInterfaceType(const ObjCInterfaceType *T) {<br>
+    // This type is handled by the parent type ObjCObjectType.<br>
+    VisitObjCObjectType(T);<br>
+  }<br>
+<br>
+  void VisitObjCTypeParamType(const ObjCTypeParamType *T) {<br>
+    AddDecl(T->getDecl());<br>
+    auto Protocols = T->getProtocols();<br>
+    ID.AddInteger(Protocols.size());<br>
+    for (auto Protocol : Protocols) {<br>
+      AddDecl(Protocol);<br>
+    }<br>
+<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitPackExpansionType(const PackExpansionType *T) {<br>
+    AddQualType(T->getPattern());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitParenType(const ParenType *T) {<br>
+    AddQualType(T->getInnerType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitPipeType(const PipeType *T) {<br>
+    AddQualType(T->getElementType());<br>
+    Hash.AddBoolean(T->isReadOnly());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
   void VisitPointerType(const PointerType *T) {<br>
     AddQualType(T->getPointeeType());<br>
     VisitType(T);<br>
@@ -744,6 +902,43 @@ public:<br>
     VisitReferenceType(T);<br>
   }<br>
<br>
+  void<br>
+  VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {<br>
+    AddType(T->getReplacedParameter());<br>
+    Hash.AddTemplateArgument(T->getArgumentPack());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {<br>
+    AddType(T->getReplacedParameter());<br>
+    AddQualType(T->getReplacementType());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitTagType(const TagType *T) {<br>
+    AddDecl(T->getDecl());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitRecordType(const RecordType *T) { VisitTagType(T); }<br>
+  void VisitEnumType(const EnumType *T) { VisitTagType(T); }<br>
+<br>
+  void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {<br>
+    ID.AddInteger(T->getNumArgs());<br>
+    for (const auto &TA : T->template_arguments()) {<br>
+      Hash.AddTemplateArgument(TA);<br>
+    }<br>
+    Hash.AddTemplateName(T->getTemplateName());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {<br>
+    ID.AddInteger(T->getDepth());<br>
+    ID.AddInteger(T->getIndex());<br>
+    Hash.AddBoolean(T->isParameterPack());<br>
+    AddDecl(T->getDecl());<br>
+  }<br>
+<br>
   void VisitTypedefType(const TypedefType *T) {<br>
     AddDecl(T->getDecl());<br>
     QualType UnderlyingType = T->getDecl()->getUnderlyingType();<br>
@@ -766,13 +961,18 @@ public:<br>
     VisitType(T);<br>
   }<br>
<br>
-  void VisitTagType(const TagType *T) {<br>
-    AddDecl(T->getDecl());<br>
+  void VisitTypeOfExprType(const TypeOfExprType *T) {<br>
+    AddStmt(T->getUnderlyingExpr());<br>
+    Hash.AddBoolean(T->isSugared());<br>
+    if (T->isSugared())<br>
+      AddQualType(T->desugar());<br>
+<br>
+    VisitType(T);<br>
+  }<br>
+  void VisitTypeOfType(const TypeOfType *T) {<br>
+    AddQualType(T->getUnderlyingType());<br>
     VisitType(T);<br>
   }<br>
-<br>
-  void VisitRecordType(const RecordType *T) { VisitTagType(T); }<br>
-  void VisitEnumType(const EnumType *T) { VisitTagType(T); }<br>
<br>
   void VisitTypeWithKeyword(const TypeWithKeyword *T) {<br>
     ID.AddInteger(T->getKeyword());<br>
@@ -802,20 +1002,26 @@ public:<br>
     VisitTypeWithKeyword(T);<br>
   }<br>
<br>
-  void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {<br>
-    ID.AddInteger(T->getNumArgs());<br>
-    for (const auto &TA : T->template_arguments()) {<br>
-      Hash.AddTemplateArgument(TA);<br>
-    }<br>
-    Hash.AddTemplateName(T->getTemplateName());<br>
+  void VisitUnaryTransformType(const UnaryTransformType *T) {<br>
+    AddQualType(T->getUnderlyingType());<br>
+    AddQualType(T->getBaseType());<br>
     VisitType(T);<br>
   }<br>
<br>
-  void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {<br>
-    ID.AddInteger(T->getDepth());<br>
-    ID.AddInteger(T->getIndex());<br>
-    Hash.AddBoolean(T->isParameterPack());<br>
+  void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {<br>
     AddDecl(T->getDecl());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitVectorType(const VectorType *T) {<br>
+    AddQualType(T->getElementType());<br>
+    ID.AddInteger(T->getNumElements());<br>
+    ID.AddInteger(T->getVectorKind());<br>
+    VisitType(T);<br>
+  }<br>
+<br>
+  void VisitExtVectorType(const ExtVectorType * T) {<br>
+    VisitVectorType(T);<br>
   }<br>
 };<br>
 } // namespace<br>
<br>
Modified: cfe/trunk/lib/AST/StmtProfile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=341421&r1=341420&r2=341421&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=341421&r1=341420&r2=341421&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Sep  4 15:53:19 2018<br>
@@ -189,7 +189,7 @@ namespace {<br>
         // store its nullness.  Add a boolean here to match.<br>
         ID.AddBoolean(true);<br>
       }<br>
-      Hash.AddDeclarationName(Name);<br>
+      Hash.AddDeclarationName(Name, TreatAsDecl);<br>
     }<br>
     void VisitIdentifierInfo(IdentifierInfo *II) override {<br>
       ID.AddBoolean(II);<br>
<br>
Modified: cfe/trunk/test/Modules/odr_hash-blocks.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash-blocks.cpp?rev=341421&r1=341420&r2=341421&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash-blocks.cpp?rev=341421&r1=341420&r2=341421&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/odr_hash-blocks.cpp (original)<br>
+++ cfe/trunk/test/Modules/odr_hash-blocks.cpp Tue Sep  4 15:53:19 2018<br>
@@ -41,7 +41,7 @@<br>
 #define ACCESS private:<br>
 #endif<br>
<br>
-// TODO: S1, S2, and S3 should generate errors.<br>
+// TODO: S1 and S2 should generate errors.<br>
 namespace Blocks {<br>
 #if defined(FIRST)<br>
 struct S1 {<br>
@@ -77,6 +77,8 @@ struct S3 {<br>
 };<br>
 #else<br>
 S3 s3;<br>
+// expected-error@first.h:* {{'Blocks::S3::run' from module 'FirstModule' is not present in definition of 'Blocks::S3' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'run' does not match}}<br>
 #endif<br>
<br>
 #define DECLS                                       \<br>
<br>
Added: cfe/trunk/test/Modules/odr_hash-gnu.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash-gnu.cpp?rev=341421&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash-gnu.cpp?rev=341421&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/odr_hash-gnu.cpp (added)<br>
+++ cfe/trunk/test/Modules/odr_hash-gnu.cpp Tue Sep  4 15:53:19 2018<br>
@@ -0,0 +1,130 @@<br>
+// Clear and create directories<br>
+// RUN: rm -rf %t<br>
+// RUN: mkdir %t<br>
+// RUN: mkdir %t/cache<br>
+// RUN: mkdir %t/Inputs<br>
+<br>
+// Build first header file<br>
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h<br>
+// RUN: cat %s               >> %t/Inputs/first.h<br>
+<br>
+// Build second header file<br>
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h<br>
+// RUN: cat %s                >> %t/Inputs/second.h<br>
+<br>
+// Test that each header can compile<br>
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/first.h<br>
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/second.h<br>
+<br>
+// Build module map file<br>
+// RUN: echo "module FirstModule {"     >> %t/Inputs/module.map<br>
+// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.map<br>
+// RUN: echo "}"                        >> %t/Inputs/module.map<br>
+// RUN: echo "module SecondModule {"    >> %t/Inputs/module.map<br>
+// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.map<br>
+// RUN: echo "}"                        >> %t/Inputs/module.map<br>
+<br>
+// Run test<br>
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=gnu++11 -fcolor-diagnostics<br>
+<br>
+#if !defined(FIRST) && !defined(SECOND)<br>
+#include "first.h"<br>
+#include "second.h"<br>
+#endif<br>
+<br>
+namespace Types {<br>
+namespace TypeOfExpr {<br>
+#if defined(FIRST)<br>
+struct Invalid1 {<br>
+  typeof(1 + 2) x;<br>
+};<br>
+double global;<br>
+struct Invalid2 {<br>
+  typeof(global) x;<br>
+};<br>
+struct Valid {<br>
+  typeof(3) x;<br>
+  typeof(x) y;<br>
+  typeof(Valid*) self;<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid1 {<br>
+  typeof(3) x;<br>
+};<br>
+int global;<br>
+struct Invalid2 {<br>
+  typeof(global) x;<br>
+};<br>
+struct Valid {<br>
+  typeof(3) x;<br>
+  typeof(x) y;<br>
+  typeof(Valid*) self;<br>
+};<br>
+#else<br>
+Invalid1 i1;<br>
+// expected-error@first.h:* {{'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')}}<br>
+// expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof (3)' (aka 'int')}}<br>
+Invalid2 i2;<br>
+// expected-error@second.h:* {{'Types::TypeOfExpr::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::TypeOfExpr::Invalid2' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+Valid v;<br>
+#endif<br>
+}  // namespace TypeOfExpr<br>
+<br>
+namespace TypeOf {<br>
+#if defined(FIRST)<br>
+struct Invalid1 {<br>
+  typeof(int) x;<br>
+};<br>
+struct Invalid2 {<br>
+  typeof(int) x;<br>
+};<br>
+using T = int;<br>
+struct Invalid3 {<br>
+  typeof(T) x;<br>
+};<br>
+struct Valid {<br>
+  typeof(int) x;<br>
+  using T = typeof(double);<br>
+  typeof(T) y;<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid1 {<br>
+  typeof(double) x;<br>
+};<br>
+using I = int;<br>
+struct Invalid2 {<br>
+  typeof(I) x;<br>
+};<br>
+using T = short;<br>
+struct Invalid3 {<br>
+  typeof(T) x;<br>
+};<br>
+struct Valid {<br>
+  typeof(int) x;<br>
+  using T = typeof(double);<br>
+  typeof(T) y;<br>
+};<br>
+#else<br>
+Invalid1 i1;<br>
+// expected-error@second.h:* {{'Types::TypeOf::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid1' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+Invalid2 i2;<br>
+// expected-error@first.h:* {{'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')}}<br>
+// expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof(Types::TypeOf::I)' (aka 'int')}}<br>
+Invalid3 i3;<br>
+// expected-error@second.h:* {{'Types::TypeOf::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid3' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+Valid v;<br>
+#endif<br>
+}  // namespace TypeOf<br>
+}  // namespace Types<br>
+<br>
+// Keep macros contained to one file.<br>
+#ifdef FIRST<br>
+#undef FIRST<br>
+#endif<br>
+<br>
+#ifdef SECOND<br>
+#undef SECOND<br>
+#endif<br>
<br>
Added: cfe/trunk/test/Modules/odr_hash-vector.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash-vector.cpp?rev=341421&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash-vector.cpp?rev=341421&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/odr_hash-vector.cpp (added)<br>
+++ cfe/trunk/test/Modules/odr_hash-vector.cpp Tue Sep  4 15:53:19 2018<br>
@@ -0,0 +1,128 @@<br>
+// Clear and create directories<br>
+// RUN: rm -rf %t<br>
+// RUN: mkdir %t<br>
+// RUN: mkdir %t/cache<br>
+// RUN: mkdir %t/Inputs<br>
+<br>
+// Build first header file<br>
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h<br>
+// RUN: cat %s               >> %t/Inputs/first.h<br>
+<br>
+// Build second header file<br>
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h<br>
+// RUN: cat %s                >> %t/Inputs/second.h<br>
+<br>
+// Test that each header can compile<br>
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 %t/Inputs/first.h -fzvector<br>
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 %t/Inputs/second.h -fzvector<br>
+<br>
+// Build module map file<br>
+// RUN: echo "module FirstModule {"     >> %t/Inputs/module.map<br>
+// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.map<br>
+// RUN: echo "}"                        >> %t/Inputs/module.map<br>
+// RUN: echo "module SecondModule {"    >> %t/Inputs/module.map<br>
+// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.map<br>
+// RUN: echo "}"                        >> %t/Inputs/module.map<br>
+<br>
+// Run test<br>
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++11 -fzvector<br>
+<br>
+#if !defined(FIRST) && !defined(SECOND)<br>
+#include "first.h"<br>
+#include "second.h"<br>
+#endif<br>
+<br>
+namespace Types {<br>
+namespace Vector {<br>
+#if defined(FIRST)<br>
+struct Invalid1 {<br>
+  __attribute((vector_size(8))) int x;<br>
+};<br>
+struct Invalid2 {<br>
+  __attribute((vector_size(8))) int x;<br>
+};<br>
+struct Invalid3 {<br>
+  __attribute((vector_size(16))) int x;<br>
+};<br>
+struct Valid {<br>
+  __attribute((vector_size(8))) int x1;<br>
+  __attribute((vector_size(16))) int x2;<br>
+  __attribute((vector_size(8))) unsigned x3;<br>
+  __attribute((vector_size(16))) long x4;<br>
+  vector unsigned x5;<br>
+  vector int x6;<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid1 {<br>
+  __attribute((vector_size(16))) int x;<br>
+};<br>
+struct Invalid2 {<br>
+  __attribute((vector_size(8))) unsigned x;<br>
+};<br>
+struct Invalid3 {<br>
+  vector unsigned x;<br>
+};<br>
+struct Valid {<br>
+  __attribute((vector_size(8))) int x1;<br>
+  __attribute((vector_size(16))) int x2;<br>
+  __attribute((vector_size(8))) unsigned x3;<br>
+  __attribute((vector_size(16))) long x4;<br>
+  vector unsigned x5;<br>
+  vector int x6;<br>
+};<br>
+#else<br>
+Invalid1 i1;<br>
+// expected-error@second.h:* {{'Types::Vector::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid1' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+Invalid2 i2;<br>
+// expected-error@second.h:* {{'Types::Vector::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid2' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+Invalid3 i3;<br>
+// expected-error@second.h:* {{'Types::Vector::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid3' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+<br>
+Valid v;<br>
+#endif<br>
+}  // namespace Vector<br>
+<br>
+<br>
+<br>
+namespace ExtVector {<br>
+}  // namespace ExtVector<br>
+#if defined(FIRST)<br>
+struct Invalid {<br>
+  using f = __attribute__((ext_vector_type(4))) float;<br>
+};<br>
+struct Valid {<br>
+  using f = __attribute__((ext_vector_type(8))) float;<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid {<br>
+  using f = __attribute__((ext_vector_type(8))) float;<br>
+};<br>
+struct Valid {<br>
+  using f = __attribute__((ext_vector_type(8))) float;<br>
+};<br>
+#else<br>
+Invalid i;<br>
+// expected-error@first.h:* {{'Types::Invalid::f' from module 'FirstModule' is not present in definition of 'Types::Invalid' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'f' does not match}}<br>
+<br>
+Valid v;<br>
+#endif<br>
+<br>
+}  // namespace Types<br>
+<br>
+<br>
+// Keep macros contained to one file.<br>
+#ifdef FIRST<br>
+#undef FIRST<br>
+#endif<br>
+<br>
+#ifdef SECOND<br>
+#undef SECOND<br>
+#endif<br>
+<br>
+#ifdef ACCESS<br>
+#undef ACCESS<br>
+#endif<br>
<br>
Added: cfe/trunk/test/Modules/<a href="http://odr_hash.cl" rel="noreferrer" target="_blank">odr_hash.cl</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cl?rev=341421&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cl?rev=341421&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/<a href="http://odr_hash.cl" rel="noreferrer" target="_blank">odr_hash.cl</a> (added)<br>
+++ cfe/trunk/test/Modules/<a href="http://odr_hash.cl" rel="noreferrer" target="_blank">odr_hash.cl</a> Tue Sep  4 15:53:19 2018<br>
@@ -0,0 +1,80 @@<br>
+// Clear and create directories<br>
+// RUN: rm -rf %t<br>
+// RUN: mkdir %t<br>
+// RUN: mkdir %t/cache<br>
+// RUN: mkdir %t/Inputs<br>
+<br>
+// Build first header file<br>
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h<br>
+// RUN: cat %s               >> %t/Inputs/first.h<br>
+<br>
+// Build second header file<br>
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h<br>
+// RUN: cat %s                >> %t/Inputs/second.h<br>
+<br>
+// Test that each header can compile<br>
+// RUN: %clang_cc1 -fsyntax-only -x c++ %t/Inputs/first.h -cl-std=CL2.0<br>
+// RUN: %clang_cc1 -fsyntax-only -x c++ %t/Inputs/second.h -cl-std=CL2.0<br>
+<br>
+// Build module map file<br>
+// RUN: echo "module FirstModule {"     >> %t/Inputs/module.map<br>
+// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.map<br>
+// RUN: echo "}"                        >> %t/Inputs/module.map<br>
+// RUN: echo "module SecondModule {"    >> %t/Inputs/module.map<br>
+// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.map<br>
+// RUN: echo "}"                        >> %t/Inputs/module.map<br>
+<br>
+// Run test<br>
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -cl-std=CL2.0<br>
+<br>
+#if !defined(FIRST) && !defined(SECOND)<br>
+#include "first.h"<br>
+#include "second.h"<br>
+#endif<br>
+<br>
+<br>
+#if defined(FIRST)<br>
+void invalid1() {<br>
+  typedef read_only pipe int x;<br>
+}<br>
+void invalid2() {<br>
+  typedef read_only pipe int x;<br>
+}<br>
+void valid() {<br>
+  typedef read_only pipe int x;<br>
+  typedef write_only pipe int y;<br>
+  typedef read_write pipe int z;<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid1() {<br>
+  typedef write_only pipe int x;<br>
+}<br>
+void invalid2() {<br>
+  typedef read_only pipe float x;<br>
+}<br>
+void valid() {<br>
+  typedef read_only pipe int x;<br>
+  typedef write_only pipe int y;<br>
+  typedef read_write pipe int z;<br>
+}<br>
+#else<br>
+void run() {<br>
+  invalid1();<br>
+// expected-error@second.h:* {{'invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+  invalid2();<br>
+// expected-error@second.h:* {{'invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+  valid();<br>
+}<br>
+#endif<br>
+<br>
+<br>
+// Keep macros contained to one file.<br>
+#ifdef FIRST<br>
+#undef FIRST<br>
+#endif<br>
+<br>
+#ifdef SECOND<br>
+#undef SECOND<br>
+#endif<br>
<br>
Modified: cfe/trunk/test/Modules/odr_hash.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=341421&r1=341420&r2=341421&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=341421&r1=341420&r2=341421&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/odr_hash.cpp (original)<br>
+++ cfe/trunk/test/Modules/odr_hash.cpp Tue Sep  4 15:53:19 2018<br>
@@ -25,7 +25,7 @@<br>
 // RUN: echo "}"                        >> %t/Inputs/module.map<br>
<br>
 // Run test<br>
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++1z<br>
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++1z -fcolor-diagnostics<br>
<br>
 #if !defined(FIRST) && !defined(SECOND)<br>
 #include "first.h"<br>
@@ -3299,6 +3299,568 @@ Valid V;<br>
 #endif<br>
 }  // namespace Enums<br>
<br>
+namespace Types {<br>
+namespace Complex {<br>
+#if defined(FIRST)<br>
+void invalid() {<br>
+  _Complex float x;<br>
+}<br>
+void valid() {<br>
+  _Complex float x;<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid() {<br>
+  _Complex double x;<br>
+}<br>
+void valid() {<br>
+  _Complex float x;<br>
+}<br>
+#else<br>
+auto function1 = invalid;<br>
+// expected-error@second.h:* {{'Types::Complex::invalid' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = valid;<br>
+#endif<br>
+}  // namespace Complex<br>
+<br>
+namespace Decltype {<br>
+#if defined(FIRST)<br>
+void invalid1() {<br>
+  decltype(1 + 1) x;<br>
+}<br>
+int global;<br>
+void invalid2() {<br>
+  decltype(global) x;<br>
+}<br>
+void valid() {<br>
+  decltype(1.5) x;<br>
+  decltype(x) y;<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid1() {<br>
+  decltype(2) x;<br>
+}<br>
+float global;<br>
+void invalid2() {<br>
+  decltype(global) x;<br>
+}<br>
+void valid() {<br>
+  decltype(1.5) x;<br>
+  decltype(x) y;<br>
+}<br>
+#else<br>
+auto function1 = invalid1;<br>
+// expected-error@second.h:* {{'Types::Decltype::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = invalid2;<br>
+// expected-error@second.h:* {{'Types::Decltype::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function3 = valid;<br>
+#endif<br>
+}  // namespace Decltype<br>
+<br>
+namespace Auto {<br>
+#if defined(FIRST)<br>
+void invalid1() {<br>
+  decltype(auto) x = 1;<br>
+}<br>
+void invalid2() {<br>
+  auto x = 1;<br>
+}<br>
+void invalid3() {<br>
+  __auto_type x = 1;<br>
+}<br>
+void valid() {<br>
+  decltype(auto) x = 1;<br>
+  auto y = 1;<br>
+  __auto_type z = 1;<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid1() {<br>
+  auto x = 1;<br>
+}<br>
+void invalid2() {<br>
+  __auto_type x = 1;<br>
+}<br>
+void invalid3() {<br>
+  decltype(auto) x = 1;<br>
+}<br>
+void valid() {<br>
+  decltype(auto) x = 1;<br>
+  auto y = 1;<br>
+  __auto_type z = 1;<br>
+}<br>
+#else<br>
+auto function1 = invalid1;<br>
+// expected-error@second.h:* {{'Types::Auto::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = invalid3;<br>
+// expected-error@second.h:* {{'Types::Auto::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function3 = invalid2;<br>
+// expected-error@second.h:* {{'Types::Auto::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function4 = valid;<br>
+#endif<br>
+}  // namespace Auto<br>
+<br>
+namespace DeducedTemplateSpecialization {<br>
+#if defined(FIRST)<br>
+template<typename T> struct A {};<br>
+A() -> A<int>;<br>
+template<typename T> struct B {};<br>
+B() -> B<int>;<br>
+<br>
+void invalid1() {<br>
+  A a{};<br>
+}<br>
+void invalid2() {<br>
+  A a{};<br>
+}<br>
+void valid() {<br>
+  B b{};<br>
+}<br>
+#elif defined(SECOND)<br>
+template<typename T> struct A {};<br>
+A() -> A<float>;<br>
+template<typename T> struct B {};<br>
+B() -> B<int>;<br>
+<br>
+void invalid1() {<br>
+  A a{};<br>
+}<br>
+void invalid2() {<br>
+  B a{};<br>
+}<br>
+void valid() {<br>
+  B b{};<br>
+}<br>
+#else<br>
+auto function1 = invalid1;<br>
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = invalid2;<br>
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function3 = valid;<br>
+#endif<br>
+}  // namespace DeducedTemplateSpecialization<br>
+<br>
+namespace DependentAddressSpace {<br>
+#if defined(FIRST)<br>
+template <int A1, int A2><br>
+void invalid1() {<br>
+  using type = int __attribute__((address_space(A1)));<br>
+}<br>
+template <int A1><br>
+void invalid2() {<br>
+  using type = float __attribute__((address_space(A1)));<br>
+}<br>
+template <int A1, int A2><br>
+void valid() {<br>
+  using type1 = float __attribute__((address_space(A1)));<br>
+  using type2 = int __attribute__((address_space(A2)));<br>
+  using type3 = int __attribute__((address_space(A1 + A2)));<br>
+}<br>
+#elif defined(SECOND)<br>
+template <int A1, int A2><br>
+void invalid1() {<br>
+  using type = int __attribute__((address_space(A2)));<br>
+}<br>
+template <int A1><br>
+void invalid2() {<br>
+  using type = int __attribute__((address_space(A1)));<br>
+}<br>
+template <int A1, int A2><br>
+void valid() {<br>
+  using type1 = float __attribute__((address_space(A1)));<br>
+  using type2 = int __attribute__((address_space(A2)));<br>
+  using type3 = int __attribute__((address_space(A1 + A2)));<br>
+}<br>
+#else<br>
+template <int A, int B><br>
+class S {<br>
+  static auto function1 = invalid1<A, B>;<br>
+  // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}<br>
+  // expected-note@second.h:* {{but in 'SecondModule' found a different body}}<br>
+  static auto function2 = invalid2<B>;<br>
+  // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}<br>
+  // expected-note@second.h:* {{but in 'SecondModule' found a different body}}<br>
+  static auto function3 = valid<A, B>;<br>
+};<br>
+#endif<br>
+}  // namespace DependentAddressSpace<br>
+<br>
+namespace DependentSizedExtVector {<br>
+#if defined(FIRST)<br>
+template<int Size><br>
+void invalid1() {<br>
+  typedef int __attribute__((ext_vector_type(Size))) type;<br>
+}<br>
+template<int Size><br>
+void invalid2() {<br>
+  typedef int __attribute__((ext_vector_type(Size + 0))) type;<br>
+}<br>
+template<int Size><br>
+void valid() {<br>
+  typedef int __attribute__((ext_vector_type(Size))) type;<br>
+}<br>
+#elif defined(SECOND)<br>
+template<int Size><br>
+void invalid1() {<br>
+  typedef float __attribute__((ext_vector_type(Size))) type;<br>
+}<br>
+template<int Size><br>
+void invalid2() {<br>
+  typedef int __attribute__((ext_vector_type(Size + 1))) type;<br>
+}<br>
+template<int Size><br>
+void valid() {<br>
+  typedef int __attribute__((ext_vector_type(Size))) type;<br>
+}<br>
+#else<br>
+template <int Num><br>
+class S {<br>
+  static auto Function1 = invalid1<Num>;<br>
+  // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}<br>
+  // expected-note@second.h:* {{but in 'SecondModule' found a different body}}<br>
+  static auto Function2 = invalid2<Num>;<br>
+  // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}<br>
+  // expected-note@second.h:* {{but in 'SecondModule' found a different body}}<br>
+  static auto Function3 = valid<Num>;<br>
+};<br>
+#endif<br>
+}  // namespace DependentSizedExtVector<br>
+<br>
+namespace InjectedClassName {<br>
+#if defined(FIRST)<br>
+struct Invalid {<br>
+  template <int><br>
+  struct L2 {<br>
+    template <int><br>
+    struct L3 {<br>
+      L3 *x;<br>
+    };<br>
+  };<br>
+};<br>
+struct Valid {<br>
+  template <int><br>
+  struct L2 {<br>
+    template <int><br>
+    struct L3 {<br>
+      L2 *x;<br>
+      L3 *y;<br>
+    };<br>
+  };<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid {<br>
+  template <int><br>
+  struct L2 {<br>
+    template <int><br>
+    struct L3 {<br>
+      L2 *x;<br>
+    };<br>
+  };<br>
+};<br>
+struct Valid {<br>
+  template <int><br>
+  struct L2 {<br>
+    template <int><br>
+    struct L3 {<br>
+      L2 *x;<br>
+      L3 *y;<br>
+    };<br>
+  };<br>
+};<br>
+#else<br>
+Invalid::L2<1>::L3<1> invalid;<br>
+// expected-error@second.h:* {{'Types::InjectedClassName::Invalid::L2::L3::x' from module 'SecondModule' is not present in definition of 'L3<>' in module 'FirstModule'}}<br>
+// expected-note@first.h:* {{declaration of 'x' does not match}}<br>
+Valid::L2<1>::L3<1> valid;<br>
+#endif<br>
+}  // namespace InjectedClassName<br>
+<br>
+namespace MemberPointer {<br>
+#if defined(FIRST)<br>
+struct A {};<br>
+struct B {};<br>
+<br>
+void Invalid1() {<br>
+  int A::*x;<br>
+};<br>
+void Invalid2() {<br>
+  int A::*x;<br>
+}<br>
+void Invalid3() {<br>
+  int (A::*x)(int);<br>
+}<br>
+void Valid() {<br>
+  int A::*x;<br>
+  float A::*y;<br>
+  bool B::*z;<br>
+  void (A::*fun1)();<br>
+  int (A::*fun2)();<br>
+  void (B::*fun3)(int);<br>
+  void (B::*fun4)(bool*, int);<br>
+}<br>
+#elif defined(SECOND)<br>
+struct A {};<br>
+struct B {};<br>
+<br>
+void Invalid1() {<br>
+  float A::*x;<br>
+};<br>
+void Invalid2() {<br>
+  int B::*x;<br>
+}<br>
+void Invalid3() {<br>
+  int (A::*x)(int, int);<br>
+}<br>
+void Valid() {<br>
+  int A::*x;<br>
+  float A::*y;<br>
+  bool B::*z;<br>
+  void (A::*fun1)();<br>
+  int (A::*fun2)();<br>
+  void (B::*fun3)(int);<br>
+  void (B::*fun4)(bool*, int);<br>
+}<br>
+#else<br>
+auto function1 = Invalid1;<br>
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = Invalid2;<br>
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function3 = Invalid3;<br>
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function4 = Valid;<br>
+#endif<br>
+<br>
+}  // namespace MemberPointer<br>
+<br>
+namespace PackExpansion {<br>
+#if defined(FIRST)<br>
+struct Invalid {<br>
+  template <class... A><br>
+  struct L2 {<br>
+    template <class... B><br>
+    struct L3 {<br>
+      void run(A...);<br>
+      void run(B...);<br>
+    };<br>
+  };<br>
+};<br>
+struct Valid {<br>
+  template <class... A><br>
+  struct L2 {<br>
+    template <class... B><br>
+    struct L3 {<br>
+      void run(A...);<br>
+      void run(B...);<br>
+    };<br>
+  };<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid {<br>
+  template <class... A><br>
+  struct L2 {<br>
+    template <class... B><br>
+    struct L3 {<br>
+      void run(B...);<br>
+      void run(A...);<br>
+    };<br>
+  };<br>
+};<br>
+struct Valid {<br>
+  template <class... A><br>
+  struct L2 {<br>
+    template <class... B><br>
+    struct L3 {<br>
+      void run(A...);<br>
+      void run(B...);<br>
+    };<br>
+  };<br>
+};<br>
+#else<br>
+Invalid::L2<int>::L3<short, bool> invalid;<br>
+// expected-error@first.h:* {{'Types::PackExpansion::Invalid::L2::L3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'run' with 1st parameter of type 'A...'}}<br>
+// expected-note@second.h:* {{but in 'SecondModule' found method 'run' with 1st parameter of type 'B...'}}<br>
+Valid::L2<int>::L3<short, bool> valid;<br>
+#endif<br>
+<br>
+}  // namespace PackExpansion<br>
+<br>
+namespace Paren {<br>
+#if defined(FIRST)<br>
+void invalid() {<br>
+  int (*x);<br>
+}<br>
+void valid() {<br>
+  int (*x);<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid() {<br>
+  float (*x);<br>
+}<br>
+void valid() {<br>
+  int (*x);<br>
+}<br>
+#else<br>
+auto function1 = invalid;<br>
+// expected-error@second.h:* {{'Types::Paren::invalid' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = valid;<br>
+#endif<br>
+}  // namespace Paren<br>
+<br>
+namespace SubstTemplateTypeParm {<br>
+#if defined(FIRST)<br>
+template <class> struct wrapper {};<br>
+template <class, class, class> struct triple {};<br>
+struct Valid {<br>
+  template <class T,<br>
+           template <class _T, class _U, class = wrapper<_T>> class A = triple><br>
+  struct L2 {<br>
+    A<T, T> x;<br>
+  };<br>
+};<br>
+#elif defined(SECOND)<br>
+template <class> struct wrapper {};<br>
+template <class, class, class> struct triple {};<br>
+struct Valid {<br>
+  template <class T,<br>
+           template <class _T, class _U, class = wrapper<_T>> class A = triple><br>
+  struct L2 {<br>
+    A<T, T> x;<br>
+  };<br>
+};<br>
+#else<br>
+template <class T,<br>
+          template <class _T, class _U, class = wrapper<_T>> class A = triple><br>
+using V = Valid::L2<T, A>;<br>
+#endif<br>
+}  // namespace SubstTemplateTypeParm<br>
+<br>
+namespace SubstTemplateTypeParmPack {<br>
+}  // namespace SubstTemplateTypeParmPack<br>
+<br>
+namespace UnaryTransform {<br>
+#if defined(FIRST)<br>
+enum class E1a : unsigned {};<br>
+struct Invalid1 {<br>
+  __underlying_type(E1a) x;<br>
+};<br>
+enum E2a : unsigned {};<br>
+struct Invalid2 {<br>
+  __underlying_type(E2a) x;<br>
+};<br>
+enum E3a {};<br>
+struct Invalid3 {<br>
+  __underlying_type(E3a) x;<br>
+};<br>
+enum E4a {};<br>
+struct Invalid4 {<br>
+  __underlying_type(E4a) x;<br>
+};<br>
+enum E1 {};<br>
+struct Valid1 {<br>
+  __underlying_type(E1) x;<br>
+};<br>
+enum E2 : unsigned {};<br>
+struct Valid2 {<br>
+  __underlying_type(E2) x;<br>
+};<br>
+enum class E3 {};<br>
+struct Valid3 {<br>
+  __underlying_type(E3) x;<br>
+};<br>
+#elif defined(SECOND)<br>
+enum class E1b : signed {};<br>
+struct Invalid1 {<br>
+  __underlying_type(E1b) x;<br>
+};<br>
+enum class E2b : unsigned {};<br>
+struct Invalid2 {<br>
+  __underlying_type(E2b) x;<br>
+};<br>
+enum E3b : int {};<br>
+struct Invalid3 {<br>
+  __underlying_type(E3b) x;<br>
+};<br>
+enum E4b {};<br>
+struct Invalid4 {<br>
+  __underlying_type(E4b) x;<br>
+};<br>
+#else<br>
+Invalid1 i1;<br>
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid1' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+Invalid2 i2;<br>
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2b)' (aka 'unsigned int')}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2a)' (aka 'unsigned int')}}<br>
+Invalid3 i3;<br>
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid3' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+Invalid4 i4;<br>
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4b)' (aka 'unsigned int')}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4a)' (aka 'unsigned int')}}<br>
+Valid1 v1;<br>
+Valid2 v2;<br>
+Valid3 v3;<br>
+#endif<br>
+}  // namespace UnaryTransform<br>
+<br>
+namespace UnresolvedUsing {<br>
+#if defined(FIRST)<br>
+template <class T> struct wrapper {};<br>
+template <class T><br>
+struct Invalid {<br>
+  using typename wrapper<T>::T1;<br>
+  using typename wrapper<T>::T2;<br>
+  T1 x;<br>
+};<br>
+template <class T><br>
+struct Valid {<br>
+  using typename wrapper<T>::T1;<br>
+  using typename wrapper<T>::T2;<br>
+  T1 x;<br>
+  T2 y;<br>
+};<br>
+#elif defined(SECOND)<br>
+template <class T> struct wrapper {};<br>
+template <class T><br>
+struct Invalid {<br>
+  using typename wrapper<T>::T1;<br>
+  using typename wrapper<T>::T2;<br>
+  T2 x;<br>
+};<br>
+template <class T><br>
+struct Valid {<br>
+  using typename wrapper<T>::T1;<br>
+  using typename wrapper<T>::T2;<br>
+  T1 x;<br>
+  T2 y;<br>
+};<br>
+#else<br>
+template <class T> using I = Invalid<T>;<br>
+// expected-error@first.h:* {{'Types::UnresolvedUsing::Invalid::x' from module 'FirstModule' is not present in definition of 'Invalid<T>' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+<br>
+template <class T> using V = Valid<T>;<br>
+#endif<br>
+<br>
+}  // namespace UnresolvedUsing<br>
+<br>
+// Vector<br>
+// void invalid1() {<br>
+//  __attribute((vector_size(8))) int *x1;<br>
+//}<br>
+<br>
+}  // namespace Types<br>
+<br>
 // Collection of interesting cases below.<br>
<br>
 // Naive parsing of AST can lead to cycles in processing.  Ensure<br>
<br>
Modified: cfe/trunk/test/Modules/<a href="http://odr_hash.mm" rel="noreferrer" target="_blank">odr_hash.mm</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.mm?rev=341421&r1=341420&r2=341421&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.mm?rev=341421&r1=341420&r2=341421&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/<a href="http://odr_hash.mm" rel="noreferrer" target="_blank">odr_hash.mm</a> (original)<br>
+++ cfe/trunk/test/Modules/<a href="http://odr_hash.mm" rel="noreferrer" target="_blank">odr_hash.mm</a> Tue Sep  4 15:53:19 2018<br>
@@ -36,14 +36,27 @@<br>
 @protocol P1<br>
 @end<br>
<br>
+@protocol P2<br>
+@end<br>
+<br>
 @interface I1<br>
 @end<br>
<br>
+@interface I2 : I1<br>
+@end<br>
+<br>
 @interface Interface1 <T : I1 *> {<br>
 @public<br>
   T<P1> x;<br>
 }<br>
 @end<br>
+<br>
+@interface Interface2 <T : I1 *><br>
+@end<br>
+<br>
+@interface Interface3 <T : I1 *><br>
+@end<br>
+<br>
 #endif<br>
<br>
 #if defined(FIRST)<br>
@@ -64,6 +77,218 @@ S s;<br>
 // expected-note@first.h:* {{declaration of 'y' does not match}}<br>
 #endif<br>
<br>
+namespace Types {<br>
+namespace Attributed {<br>
+#if defined(FIRST)<br>
+void invalid1() {<br>
+  static double __attribute((objc_gc(strong))) *x;<br>
+}<br>
+void invalid2() {<br>
+  static int __attribute((objc_gc(strong))) *x;<br>
+}<br>
+void valid() {<br>
+  static int __attribute((objc_gc(strong))) *x;<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid1() {<br>
+  static int __attribute((objc_gc(strong))) *x;<br>
+}<br>
+void invalid2() {<br>
+  static int __attribute((objc_gc(weak))) *x;<br>
+}<br>
+void valid() {<br>
+  static int __attribute((objc_gc(strong))) *x;<br>
+}<br>
+#else<br>
+auto function1 = invalid1;<br>
+// expected-error@second.h:* {{Types::Attributed::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = invalid2;<br>
+// expected-error@second.h:* {{'Types::Attributed::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function3 = valid;<br>
+#endif<br>
+}  // namespace Attributed<br>
+<br>
+namespace BlockPointer {<br>
+#if defined(FIRST)<br>
+void invalid1() {<br>
+  void (^x)(int);<br>
+}<br>
+void invalid2() {<br>
+  void (^x)(int);<br>
+}<br>
+void invalid3() {<br>
+  void (^x)(int);<br>
+}<br>
+void invalid4() {<br>
+  void (^x)(int);<br>
+}<br>
+void valid() {<br>
+  void (^x1)(int);<br>
+  int (^x2)(int);<br>
+  void (^x3)(int, int);<br>
+  void (^x4)(short);<br>
+}<br>
+#elif defined(SECOND)<br>
+void invalid1() {<br>
+  void (^x)();<br>
+}<br>
+void invalid2() {<br>
+  void (^x)(int, int);<br>
+}<br>
+void invalid3() {<br>
+  int (^x)(int);<br>
+}<br>
+void invalid4() {<br>
+  void (^x)(float);<br>
+}<br>
+void valid() {<br>
+  void (^x1)(int);<br>
+  int (^x2)(int);<br>
+  void (^x3)(int, int);<br>
+  void (^x4)(short);<br>
+}<br>
+#else<br>
+auto function1 = invalid1;<br>
+// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function2 = invalid2;<br>
+// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function3 = invalid3;<br>
+// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function4 = invalid4;<br>
+// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}<br>
+auto function5 = valid;<br>
+#endif<br>
+}  // namespace BlockPointer<br>
+<br>
+namespace ObjCObject {<br>
+#if defined(FIRST)<br>
+struct Invalid1 {<br>
+  using T = Interface2<I1*>;<br>
+};<br>
+struct Invalid2 {<br>
+  using T = Interface2<I1*>;<br>
+};<br>
+struct Invalid3 {<br>
+  using T = Interface2<P1, P1>;<br>
+};<br>
+struct Invalid4 {<br>
+  using T = Interface2<P1>;<br>
+};<br>
+struct Valid {<br>
+  using T1 = Interface2<I1*>;<br>
+  using T2 = Interface3<I1*>;<br>
+  using T3 = Interface2<P1>;<br>
+  using T4 = Interface3<P1, P2>;<br>
+  using T5 = __kindof Interface2;<br>
+};<br>
+#elif defined(SECOND)<br>
+struct Invalid1 {<br>
+  using T = Interface3<I1*>;<br>
+};<br>
+struct Invalid2 {<br>
+  using T = Interface2<I2*>;<br>
+};<br>
+struct Invalid3 {<br>
+  using T = Interface2<P1>;<br>
+};<br>
+struct Invalid4 {<br>
+  using T = Interface2<P2>;<br>
+};<br>
+struct Valid {<br>
+  using T1 = Interface2<I1*>;<br>
+  using T2 = Interface3<I1*>;<br>
+  using T3 = Interface2<P1>;<br>
+  using T4 = Interface3<P1, P2>;<br>
+  using T5 = __kindof Interface2;<br>
+};<br>
+#else<br>
+Invalid1 i1;<br>
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'T' does not match}}<br>
+Invalid2 i2;<br>
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'T' does not match}}<br>
+Invalid3 i3;<br>
+// expected-error@second.h:* {{'Types::ObjCObject::Invalid3' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'Interface2<P1>'}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}<br>
+Invalid4 i4;<br>
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'T' does not match}}<br>
+Valid v;<br>
+#endif<br>
+}  // namespace VisitObjCObject<br>
+}  // namespace Types<br>
+<br>
+#if defined(FIRST)<br>
+@interface Interface4 <T : I1 *> {<br>
+@public<br>
+  T<P1> x;<br>
+}<br>
+@end<br>
+@interface Interface5 <T : I1 *> {<br>
+@public<br>
+  T<P1> x;<br>
+}<br>
+@end<br>
+@interface Interface6 <T1 : I1 *, T2 : I2 *> {<br>
+@public<br>
+  T1 x;<br>
+}<br>
+@end<br>
+#elif defined(SECOND)<br>
+@interface Interface4 <T : I1 *> {<br>
+@public<br>
+  T<P2> x;<br>
+}<br>
+@end<br>
+@interface Interface5 <T : I1 *> {<br>
+@public<br>
+  T<P1, P2> x;<br>
+}<br>
+@end<br>
+@interface Interface6 <T1 : I1 *, T2 : I2 *> {<br>
+@public<br>
+  T2 x;<br>
+}<br>
+@end<br>
+#endif<br>
+<br>
+namespace Types {<br>
+namespace ObjCTypeParam {<br>
+#if defined(FIRST) || defined(SECOND)<br>
+struct Invalid1 {<br>
+  Interface4 *I;<br>
+  decltype(I->x) x;<br>
+};<br>
+struct Invalid2 {<br>
+  Interface5 *I;<br>
+  decltype(I->x) x;<br>
+};<br>
+struct Invalid3 {<br>
+  Interface6 *I;<br>
+  decltype(I->x) x;<br>
+};<br>
+#else<br>
+Invalid1 i1;<br>
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+Invalid2 i2;<br>
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+Invalid3 i3;<br>
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+#endif<br>
+<br>
+}  // namespace ObjCTypeParam<br>
+}  // namespace Types<br>
+<br>
 // Keep macros contained to one file.<br>
 #ifdef FIRST<br>
 #undef FIRST<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>
</blockquote></div>