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
