Author: rtrieu Date: Wed Aug 29 18:57:52 2018 New Revision: 341013 URL: http://llvm.org/viewvc/llvm-project?rev=341013&view=rev Log: Ensure canonical type is actually canonical.
ASTContext::applyObjCProtocolQualifiers will return a canonical type when given a canonical type and an array of canonical protocols. If the protocols are not canonical then the returned type is also not canonical. Since a canonical type is needed, canonicalize the returned type before using it. This later prevents a type from having a non-canonical canonical type. Added: cfe/trunk/test/Modules/odr_hash.mm Modified: cfe/trunk/lib/AST/ASTContext.cpp Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=341013&r1=341012&r2=341013&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Aug 29 18:57:52 2018 @@ -4550,8 +4550,8 @@ ASTContext::getObjCTypeParamType(const O if (!protocols.empty()) { // Apply the protocol qualifers. bool hasError; - Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError, - true/*allowOnPointerType*/); + Canonical = getCanonicalType(applyObjCProtocolQualifiers( + Canonical, protocols, hasError, true /*allowOnPointerType*/)); assert(!hasError && "Error when apply protocol qualifier to bound type"); } } Added: cfe/trunk/test/Modules/odr_hash.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.mm?rev=341013&view=auto ============================================================================== --- cfe/trunk/test/Modules/odr_hash.mm (added) +++ cfe/trunk/test/Modules/odr_hash.mm Wed Aug 29 18:57:52 2018 @@ -0,0 +1,74 @@ +// 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 objective-c++ %t/Inputs/first.h -fblocks -fobjc-arc +// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/second.h -fblocks -fobjc-arc + +// 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 objective-c++ -I%t/Inputs -verify %s -fblocks -fobjc-arc + +#if !defined(FIRST) && !defined(SECOND) +#include "first.h" +#include "second.h" +#endif + +#if defined(FIRST) || defined(SECOND) +@protocol P1 +@end + +@interface I1 +@end + +@interface Interface1 <T : I1 *> { +@public + T<P1> x; +} +@end +#endif + +#if defined(FIRST) +struct S { + Interface1 *I; + decltype(I->x) x; + int y; +}; +#elif defined(SECOND) +struct S { + Interface1 *I; + decltype(I->x) x; + bool y; +}; +#else +S s; +// expected-error@second.h:* {{'S::y' from module 'SecondModule' is not present in definition of 'S' in module 'FirstModule'}} +// expected-note@first.h:* {{declaration of 'y' does not match}} +#endif + +// Keep macros contained to one file. +#ifdef FIRST +#undef FIRST +#endif + +#ifdef SECOND +#undef SECOND +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits