I’ve come up with a patch and sent it to the list today since it is urgent to fix.
https://reviews.llvm.org/D24110 <https://reviews.llvm.org/D24110> Thank you. > On Aug 31, 2016, at 1:50 PM, Vassil Vassilev <v.g.vassi...@gmail.com> wrote: > > Hi Akira, > Thanks for your email. I am on vacation right now and I will try to look at > this issue as soon as I can. > Sorry for the inconvenience. > Cheers, > Vassil > On 31/08/16 22:56, Akira Hatanaka wrote: >> Vassil and Richard, >> >> After this commit, clang errors out when compiling the following code, which >> used to compile without any errors. >> >> $ cat f2.cpp >> extern int compile_time_assert_failed[1]; >> >> template <typename > >> class C { >> enum { D }; >> public: >> template <typename A> void foo1() { >> extern int compile_time_assert_failed[ ((int)C<A>::k > (int)D) ? 1 : -1]; >> } >> }; >> >> template<> >> class C<int> { >> public: >> const static int k = 2; >> }; >> >> void foo2() { >> C<char> c; >> c.foo1<int>(); >> } >> >> $ cat f3.cpp >> void foo1() { >> extern int foo0[1]; >> } >> >> template<int n> >> void foo2() { >> extern int foo0[n ? 1 : -1]; >> } >> >> void foo3() { >> foo2<5>(); >> } >> >> The code looks legal, so I don’t think clang should complain? >> >>> On Feb 28, 2016, at 11:08 AM, Vassil Vassilev via cfe-commits >>> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote: >>> >>> Author: vvassilev >>> Date: Sun Feb 28 13:08:24 2016 >>> New Revision: 262189 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=262189&view=rev >>> <http://llvm.org/viewvc/llvm-project?rev=262189&view=rev> >>> Log: >>> [modules] Prefer more complete array types. >>> >>> If we import a module that has a complete array type and one that has an >>> incomplete array type, the declaration found by name lookup might be the >>> one with >>> the incomplete type, possibly resulting in rejects-valid. >>> >>> Now, the name lookup prefers decls with a complete array types. Also, >>> diagnose cases when the redecl chain has array bound, different from the >>> merge >>> candidate. >>> >>> Reviewed by Richard Smith. >>> >>> Modified: >>> cfe/trunk/lib/Sema/SemaDecl.cpp >>> cfe/trunk/lib/Sema/SemaLookup.cpp >>> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp >>> cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp >>> cfe/trunk/test/Modules/Inputs/PR26179/A.h >>> cfe/trunk/test/Modules/Inputs/PR26179/B.h >>> cfe/trunk/test/Modules/Inputs/PR26179/basic_string.h >>> >>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Feb 28 13:08:24 2016 >>> @@ -3245,6 +3245,22 @@ void Sema::mergeObjCMethodDecls(ObjCMeth >>> CheckObjCMethodOverride(newMethod, oldMethod); >>> } >>> >>> +static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* >>> Old) { >>> + assert(!S.Context.hasSameType(New->getType(), Old->getType())); >>> + >>> + S.Diag(New->getLocation(), New->isThisDeclarationADefinition() >>> + ? diag::err_redefinition_different_type >>> + : diag::err_redeclaration_different_type) >>> + << New->getDeclName() << New->getType() << Old->getType(); >>> + >>> + diag::kind PrevDiag; >>> + SourceLocation OldLocation; >>> + std::tie(PrevDiag, OldLocation) >>> + = getNoteDiagForInvalidRedeclaration(Old, New); >>> + S.Diag(OldLocation, PrevDiag); >>> + New->setInvalidDecl(); >>> +} >>> + >>> /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name >>> and >>> /// scope as a previous declaration 'Old'. Figure out how to merge their >>> types, >>> /// emitting diagnostics as appropriate. >>> @@ -3271,21 +3287,40 @@ void Sema::MergeVarDeclTypes(VarDecl *Ne >>> // object or function shall be identical, except that declarations >>> for an >>> // array object can specify array types that differ by the presence or >>> // absence of a major array bound (8.3.4). >>> - else if (Old->getType()->isIncompleteArrayType() && >>> - New->getType()->isArrayType()) { >>> - const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); >>> - const ArrayType *NewArray = Context.getAsArrayType(New->getType()); >>> - if (Context.hasSameType(OldArray->getElementType(), >>> - NewArray->getElementType())) >>> - MergedT = New->getType(); >>> - } else if (Old->getType()->isArrayType() && >>> - New->getType()->isIncompleteArrayType()) { >>> + else if (Old->getType()->isArrayType() && >>> New->getType()->isArrayType()) { >>> const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); >>> const ArrayType *NewArray = Context.getAsArrayType(New->getType()); >>> - if (Context.hasSameType(OldArray->getElementType(), >>> - NewArray->getElementType())) >>> - MergedT = Old->getType(); >>> - } else if (New->getType()->isObjCObjectPointerType() && >>> + >>> + // We are merging a variable declaration New into Old. If it has an >>> array >>> + // bound, and that bound differs from Old's bound, we should >>> diagnose the >>> + // mismatch. >>> + if (!NewArray->isIncompleteArrayType()) { >>> + for (VarDecl *PrevVD = Old->getMostRecentDecl(); PrevVD; >>> + PrevVD = PrevVD->getPreviousDecl()) { >>> + const ArrayType *PrevVDTy = >>> Context.getAsArrayType(PrevVD->getType()); >>> + if (PrevVDTy->isIncompleteArrayType()) >>> + continue; >>> + >>> + if (!Context.hasSameType(NewArray, PrevVDTy)) >>> + return diagnoseVarDeclTypeMismatch(*this, New, PrevVD); >>> + } >>> + } >>> + >>> + if (OldArray->isIncompleteArrayType() && NewArray->isArrayType()) { >>> + if (Context.hasSameType(OldArray->getElementType(), >>> + NewArray->getElementType())) >>> + MergedT = New->getType(); >>> + } >>> + // FIXME: Check visibility. New is hidden but has a complete type. >>> If New >>> + // has no array bound, it should not inherit one from Old, if Old is >>> not >>> + // visible. >>> + else if (OldArray->isArrayType() && >>> NewArray->isIncompleteArrayType()) { >>> + if (Context.hasSameType(OldArray->getElementType(), >>> + NewArray->getElementType())) >>> + MergedT = Old->getType(); >>> + } >>> + } >>> + else if (New->getType()->isObjCObjectPointerType() && >>> Old->getType()->isObjCObjectPointerType()) { >>> MergedT = Context.mergeObjCGCQualifiers(New->getType(), >>> Old->getType()); >>> @@ -3311,27 +3346,7 @@ void Sema::MergeVarDeclTypes(VarDecl *Ne >>> New->setType(Context.DependentTy); >>> return; >>> } >>> - >>> - // FIXME: Even if this merging succeeds, some other non-visible >>> declaration >>> - // of this variable might have an incompatible type. For instance: >>> - // >>> - // extern int arr[]; >>> - // void f() { extern int arr[2]; } >>> - // void g() { extern int arr[3]; } >>> - // >>> - // Neither C nor C++ requires a diagnostic for this, but we should >>> still try >>> - // to diagnose it. >>> - Diag(New->getLocation(), New->isThisDeclarationADefinition() >>> - ? diag::err_redefinition_different_type >>> - : diag::err_redeclaration_different_type) >>> - << New->getDeclName() << New->getType() << Old->getType(); >>> - >>> - diag::kind PrevDiag; >>> - SourceLocation OldLocation; >>> - std::tie(PrevDiag, OldLocation) = >>> - getNoteDiagForInvalidRedeclaration(Old, New); >>> - Diag(OldLocation, PrevDiag); >>> - return New->setInvalidDecl(); >>> + return diagnoseVarDeclTypeMismatch(*this, New, Old); >>> } >>> >>> // Don't actually update the type on the new declaration if the old >>> >>> Modified: cfe/trunk/lib/Sema/SemaLookup.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Sun Feb 28 13:08:24 2016 >>> @@ -419,6 +419,18 @@ static bool isPreferredLookupResult(Sema >>> } >>> } >>> >>> + // VarDecl can have incomplete array types, prefer the one with more >>> complete >>> + // array type. >>> + if (VarDecl *DVD = dyn_cast<VarDecl>(DUnderlying)) { >>> + VarDecl *EVD = cast<VarDecl>(EUnderlying); >>> + if (EVD->getType()->isIncompleteType() && >>> + !DVD->getType()->isIncompleteType()) { >>> + // Prefer the decl with a more complete type if visible. >>> + return S.isVisible(DVD); >>> + } >>> + return false; // Avoid picking up a newer decl, just because it was >>> newer. >>> + } >>> + >>> // For most kinds of declaration, it doesn't really matter which one we >>> pick. >>> if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) { >>> // If the existing declaration is hidden, prefer the new one. Otherwise, >>> >>> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) >>> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sun Feb 28 13:08:24 2016 >>> @@ -2613,7 +2613,7 @@ static bool isSameEntity(NamedDecl *X, N >>> // template <typename T> struct S { static T Var[]; }; // #1 >>> // template <typename T> T S<T>::Var[sizeof(T)]; // #2 >>> // Only? happens when completing an incomplete array type. In this >>> case >>> - // when comparing #1 and #2 we should go through their elements >>> types. >>> + // when comparing #1 and #2 we should go through their element type. >>> const ArrayType *VarXTy = C.getAsArrayType(VarX->getType()); >>> const ArrayType *VarYTy = C.getAsArrayType(VarY->getType()); >>> if (!VarXTy || !VarYTy) >>> >>> Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp (original) >>> +++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp Sun Feb 28 >>> 13:08:24 2016 >>> @@ -207,3 +207,7 @@ namespace use_outside_ns { >>> int j() { return sizeof(d); } >>> } >>> } >>> + >>> +extern int arr[]; >>> +void f1() { extern int arr[2]; } // expected-note {{previous}} >>> +void f2() { extern int arr[3]; } // expected-error {{different type: 'int >>> [3]' vs 'int [2]'}} >>> >>> Modified: cfe/trunk/test/Modules/Inputs/PR26179/A.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR26179/A.h?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR26179/A.h?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/test/Modules/Inputs/PR26179/A.h (original) >>> +++ cfe/trunk/test/Modules/Inputs/PR26179/A.h Sun Feb 28 13:08:24 2016 >>> @@ -1,4 +1,2 @@ >>> #include "basic_string.h" >>> #include "B.h" >>> - >>> -int *p = a; >>> >>> Modified: cfe/trunk/test/Modules/Inputs/PR26179/B.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR26179/B.h?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR26179/B.h?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/test/Modules/Inputs/PR26179/B.h (original) >>> +++ cfe/trunk/test/Modules/Inputs/PR26179/B.h Sun Feb 28 13:08:24 2016 >>> @@ -1,2 +1 @@ >>> #include "basic_string.h" >>> -extern int a[5]; >>> >>> Modified: cfe/trunk/test/Modules/Inputs/PR26179/basic_string.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR26179/basic_string.h?rev=262189&r1=262188&r2=262189&view=diff >>> >>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR26179/basic_string.h?rev=262189&r1=262188&r2=262189&view=diff> >>> ============================================================================== >>> --- cfe/trunk/test/Modules/Inputs/PR26179/basic_string.h (original) >>> +++ cfe/trunk/test/Modules/Inputs/PR26179/basic_string.h Sun Feb 28 >>> 13:08:24 2016 >>> @@ -9,6 +9,4 @@ struct basic_string { >>> template<typename T> >>> T basic_string<T>::_S_empty_rep_storage[sizeof(T)]; >>> >>> -extern int a[]; >>> - >>> #endif >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits> >> >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits