From 35db833915e85f768ac95feb529a0c48c5663454 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Thu, 30 Aug 2018 01:57:52 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341013 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTContext.cpp | 4 +-- test/Modules/odr_hash.mm | 74 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 test/Modules/odr_hash.mm diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 098abf2063..ab2a95e577 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4550,8 +4550,8 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, 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"); } } diff --git a/test/Modules/odr_hash.mm b/test/Modules/odr_hash.mm new file mode 100644 index 0000000000..724ed95dc1 --- /dev/null +++ b/test/Modules/odr_hash.mm @@ -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 { +@public + T 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 -- 2.40.0