r341421 - [ODRHash] Extend hash to support all Type's.

Richard Trieu via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 5 14:58:22 PDT 2018


Galina,

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.

Richard

On Wed, Sep 5, 2018 at 1:45 PM Galina Kistanova <gkistanova at gmail.com>
wrote:

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


More information about the cfe-commits mailing list