Committed with a few tweaks as r190439.
On Mon, Sep 9, 2013 at 7:20 PM, Serge Pavlov <[email protected]> wrote: > Friedly ping. > > > 2013/8/30 Serge Pavlov <[email protected]> > >> Added giagnostics related to constexpr. >> Error is produced by the code that expects constexpr. However issuing a >> message why the >> expression is not constant is more user friendly. With this patch >> compiler generates an >> appropriate note, similar to other cases in expression evaluators. >> CCEDiag is used to >> report the message as this is core constant expression violation. >> >> Hi rsmith, >> >> http://llvm-reviews.chandlerc.com/D637 >> >> CHANGE SINCE LAST DIFF >> http://llvm-reviews.chandlerc.com/D637?vs=3863&id=3913#toc >> >> Files: >> include/clang/Basic/DiagnosticASTKinds.td >> include/clang/Basic/DiagnosticSemaKinds.td >> lib/AST/ExprConstant.cpp >> lib/Sema/SemaExpr.cpp >> test/Sema/empty1.c >> test/SemaCXX/empty1.cpp >> >> Index: include/clang/Basic/DiagnosticASTKinds.td >> =================================================================== >> --- include/clang/Basic/DiagnosticASTKinds.td >> +++ include/clang/Basic/DiagnosticASTKinds.td >> @@ -139,6 +139,8 @@ >> def warn_integer_constant_overflow : Warning< >> "overflow in expression; result is %0 with type %1">, >> InGroup<DiagGroup<"integer-overflow">>; >> +def note_undefined_is_not_constexpr : Note<"operation with undefined >> behavior " >> + "cannot be used in constant expression">; >> >> // inline asm related. >> let CategoryName = "Inline Assembly Issue" in { >> Index: include/clang/Basic/DiagnosticSemaKinds.td >> =================================================================== >> --- include/clang/Basic/DiagnosticSemaKinds.td >> +++ include/clang/Basic/DiagnosticSemaKinds.td >> @@ -4179,6 +4179,9 @@ >> def warn_offsetof_non_standardlayout_type : ExtWarn< >> "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>; >> def err_offsetof_bitfield : Error<"cannot compute offset of bit-field >> %0">; >> +def warn_sub_ptr_zero_size_types : Warning< >> + "subtraction of pointers to type %0 of zero size has undefined >> behavior">, >> + InGroup<PointerArith>; >> >> def warn_floatingpoint_eq : Warning< >> "comparing floating point with == or != is unsafe">, >> Index: lib/AST/ExprConstant.cpp >> =================================================================== >> --- lib/AST/ExprConstant.cpp >> +++ lib/AST/ExprConstant.cpp >> @@ -6570,6 +6570,17 @@ >> if (!HandleSizeof(Info, E->getExprLoc(), ElementType, >> ElementSize)) >> return false; >> >> + // As an extension, a type may have zero size (empty struct or >> union in >> + // C, array of zero length). Meaning of pointer difference in >> such >> + // case is unspecified. >> + if (ElementSize.isZero()) { >> + // C++11 [expr.const]p2: >> + // A conditional-expression is a core constant expression >> unless it >> + // involves ... an operation that would have undefined >> behavior... >> + CCEDiag(E, diag::note_undefined_is_not_constexpr); >> + return false; >> + } >> + >> // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at >> runtime, >> // and produce incorrect results when it overflows. Such behavior >> // appears to be non-conforming, but is common, so perhaps we >> should >> Index: lib/Sema/SemaExpr.cpp >> =================================================================== >> --- lib/Sema/SemaExpr.cpp >> +++ lib/Sema/SemaExpr.cpp >> @@ -7040,6 +7040,18 @@ >> LHS.get(), RHS.get())) >> return QualType(); >> >> + // The pointee type may have zero size. As an extension, a >> structure or >> + // union may have zero size or an array may have zero length. In >> this >> + // case subtraction does not make sense. >> + if (!rpointee->isVoidType() && !rpointee->isFunctionType()) { >> + CharUnits ElementSize = Context.getTypeSizeInChars(rpointee); >> + if (ElementSize.isZero()) { >> + Diag(Loc,diag::warn_sub_ptr_zero_size_types) >> + << rpointee.getUnqualifiedType() >> + << LHS.get()->getSourceRange() << >> RHS.get()->getSourceRange(); >> + } >> + } >> + >> if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); >> return Context.getPointerDiffType(); >> } >> Index: test/Sema/empty1.c >> =================================================================== >> --- test/Sema/empty1.c >> +++ test/Sema/empty1.c >> @@ -36,3 +36,50 @@ >> struct emp_1 f1; >> union emp_2 f2; >> }; >> + >> + >> +// Checks for pointer subtraction (PR15683) >> + >> +struct emp_1* func_1p (struct emp_1* x) { >> + return x - 5; >> +} >> + >> +int func_1 () { >> + struct emp_1 v[1]; >> + return v - v; // expected-warning {{subtraction of pointers to type >> 'struct emp_1' of zero size has undefined behavior}} >> +} >> + >> +int func_2 (struct emp_1* x) { >> + return 1 + x - x; // expected-warning {{subtraction of pointers to >> type 'struct emp_1' of zero size has undefined behavior}} >> +} >> + >> +int func_3 (struct emp_1* x, struct emp_1* y) { >> + return x - y; // expected-warning {{subtraction of pointers to type >> 'struct emp_1' of zero size has undefined behavior}} >> +} >> + >> +int func_4 (struct emp_1* x, const struct emp_1* y) { >> + return x - y; // expected-warning {{subtraction of pointers to type >> 'struct emp_1' of zero size has undefined behavior}} >> +} >> + >> +int func_5 (volatile struct emp_1* x, const struct emp_1* y) { >> + return x - y; // expected-warning {{subtraction of pointers to type >> 'struct emp_1' of zero size has undefined behavior}} >> +} >> + >> +int func_6 () { >> + union emp_2 v[1]; >> + return v - v; // expected-warning {{subtraction of pointers to type >> 'union emp_2' of zero size has undefined behavior}} >> +} >> + >> +struct A; // expected-note {{forward declaration of 'struct A'}} >> + >> +int func_7 (struct A* x, struct A* y) { >> + return x - y; // expected-error {{arithmetic on a pointer to an >> incomplete type 'struct A'}} >> +} >> + >> +int func_8 (struct emp_1 (*x)[10], struct emp_1 (*y)[10]) { >> + return x - y; // expected-warning {{subtraction of pointers to type >> 'struct emp_1 [10]' of zero size has undefined behavior}} >> +} >> + >> +int func_9 (struct emp_1 (*x)[], struct emp_1 (*y)[]) { >> + return x - y; // expected-error {{arithmetic on a pointer to an >> incomplete type 'struct emp_1 []'}} >> +} >> Index: test/SemaCXX/empty1.cpp >> =================================================================== >> --- /dev/null >> +++ test/SemaCXX/empty1.cpp >> @@ -0,0 +1,19 @@ >> +// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify >> + >> +int func_1(int (*p1)[0], int (*p2)[0]) { >> + return p1 - p2; // expected-warning {{subtraction of pointers to type >> 'int [0]' of zero size has undefined behavior}} >> +} >> + >> +constexpr int (*p1)[0] = 0, (*p2)[0] = 0; >> +constexpr int k = p2 - p1; // expected-warning {{subtraction of >> pointers to type 'int [0]' of zero size has undefined behavior}} \ >> + // expected-note {{operation with undefined >> behavior cannot be used in constant expression}} \ >> + // expected-error {{constexpr variable 'k' >> must be initialized by a constant expression}} >> + >> +constexpr int func_2(int (*x1)[0], int (*x2)[0]) { >> + return x1 - x2; // expected-warning {{subtraction of pointers to type >> 'int [0]' of zero size has undefined behavior}} >> +} >> + >> +constexpr int func_3(int (*x1)[0], long (*x2)[0]) { >> + return x1 - x2; // expected-error {{int (*)[0]' and 'long (*)[0]' are >> not pointers to compatible types}} \ >> + // expected-warning {{of zero size has undefined >> behavior}} >> +} >> > > > > -- > Thanks, > --Serge >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
