This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG9092acc51010: [clang][Interp] Emit proper diagnostic when comparing unrelated pointers (authored by tbaeder).
Changed prior to commit: https://reviews.llvm.org/D149172?vs=516847&id=545097#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D149172/new/ https://reviews.llvm.org/D149172 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Pointer.cpp clang/test/AST/Interp/literals.cpp Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -122,6 +122,35 @@ static_assert(!!FP, ""); } +namespace PointerComparison { + + struct S { int a, b; } s; + constexpr void *null = 0; + constexpr void *pv = (void*)&s.a; + constexpr void *qv = (void*)&s.b; + constexpr bool v1 = null < (int*)0; + constexpr bool v2 = null < pv; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} \ + + constexpr bool v3 = null == pv; // ok + constexpr bool v4 = qv == pv; // ok + + /// FIXME: These two are rejected by the current interpreter, but + /// accepted by GCC. + constexpr bool v5 = qv >= pv; // ref-error {{constant expression}} \ + // ref-note {{unequal pointers to void}} + constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \ + // ref-note {{unequal pointers to void}} + constexpr bool v6 = qv > null; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} + + constexpr bool v7 = qv <= (void*)&s.b; // ok +} + namespace SizeOf { constexpr int soint = sizeof(int); constexpr int souint = sizeof(unsigned int); Index: clang/lib/AST/Interp/Pointer.cpp =================================================================== --- clang/lib/AST/Interp/Pointer.cpp +++ clang/lib/AST/Interp/Pointer.cpp @@ -145,6 +145,13 @@ return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr); } +std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const { + if (!Pointee) + return "nullptr"; + + return toAPValue().getAsString(Ctx, getType()); +} + bool Pointer::isInitialized() const { assert(Pointee && "Cannot check if null pointer was initialized"); const Descriptor *Desc = getFieldDesc(); Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -701,7 +701,9 @@ if (!Pointer::hasSameBase(LHS, RHS)) { const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); + S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified) + << LHS.toDiagnosticString(S.getCtx()) + << RHS.toDiagnosticString(S.getCtx()); return false; } else { unsigned VL = LHS.getByteOffset(); Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -143,6 +143,7 @@ case CK_NonAtomicToAtomic: case CK_NoOp: case CK_UserDefinedConversion: + case CK_BitCast: return this->visit(SubExpr); case CK_IntegralToBoolean:
Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -122,6 +122,35 @@ static_assert(!!FP, ""); } +namespace PointerComparison { + + struct S { int a, b; } s; + constexpr void *null = 0; + constexpr void *pv = (void*)&s.a; + constexpr void *qv = (void*)&s.b; + constexpr bool v1 = null < (int*)0; + constexpr bool v2 = null < pv; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} \ + + constexpr bool v3 = null == pv; // ok + constexpr bool v4 = qv == pv; // ok + + /// FIXME: These two are rejected by the current interpreter, but + /// accepted by GCC. + constexpr bool v5 = qv >= pv; // ref-error {{constant expression}} \ + // ref-note {{unequal pointers to void}} + constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \ + // ref-note {{unequal pointers to void}} + constexpr bool v6 = qv > null; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} + + constexpr bool v7 = qv <= (void*)&s.b; // ok +} + namespace SizeOf { constexpr int soint = sizeof(int); constexpr int souint = sizeof(unsigned int); Index: clang/lib/AST/Interp/Pointer.cpp =================================================================== --- clang/lib/AST/Interp/Pointer.cpp +++ clang/lib/AST/Interp/Pointer.cpp @@ -145,6 +145,13 @@ return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr); } +std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const { + if (!Pointee) + return "nullptr"; + + return toAPValue().getAsString(Ctx, getType()); +} + bool Pointer::isInitialized() const { assert(Pointee && "Cannot check if null pointer was initialized"); const Descriptor *Desc = getFieldDesc(); Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -701,7 +701,9 @@ if (!Pointer::hasSameBase(LHS, RHS)) { const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); + S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified) + << LHS.toDiagnosticString(S.getCtx()) + << RHS.toDiagnosticString(S.getCtx()); return false; } else { unsigned VL = LHS.getByteOffset(); Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -143,6 +143,7 @@ case CK_NonAtomicToAtomic: case CK_NoOp: case CK_UserDefinedConversion: + case CK_BitCast: return this->visit(SubExpr); case CK_IntegralToBoolean:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits