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

Galina Kistanova via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 5 13:44:54 PDT 2018


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/076b43b9/attachment-0001.html>


More information about the cfe-commits mailing list