]> granicus.if.org Git - clang/commitdiff
PR38095: Allow constant-folding of loads through bitcasted pointers if
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 11 Jul 2018 00:29:05 +0000 (00:29 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 11 Jul 2018 00:29:05 +0000 (00:29 +0000)
the bitcast only changed cvr-qualifications within the pointer type.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336746 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
test/Sema/diagnose_if.c

index 828368a3e12ab9f25c3e827cf888285c39bf9462..bf21bc65e2bf3d1453bda60fee0d74c1be09d281 100644 (file)
@@ -5787,8 +5787,8 @@ bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
   return evaluateLValue(E->getSubExpr(), Result);
 }
 
-bool PointerExprEvaluator::VisitCastExpr(const CastExprE) {
-  const ExprSubExpr = E->getSubExpr();
+bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
+  const Expr *SubExpr = E->getSubExpr();
 
   switch (E->getCastKind()) {
   default:
@@ -5805,7 +5805,11 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
     // permitted in constant expressions in C++11. Bitcasts from cv void* are
     // also static_casts, but we disallow them as a resolution to DR1312.
     if (!E->getType()->isVoidPointerType()) {
-      Result.Designator.setInvalid();
+      // If we changed anything other than cvr-qualifiers, we can't use this
+      // value for constant folding. FIXME: Qualification conversions should
+      // always be CK_NoOp, but we get this wrong in C.
+      if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType()))
+        Result.Designator.setInvalid();
       if (SubExpr->getType()->isVoidPointerType())
         CCEDiag(E, diag::note_constexpr_invalid_cast)
           << 3 << SubExpr->getType();
index 38a3307d924a5d37a48dc7760e68c85ad1c2a8b0..00bb4770f053aa7c28006461271304d955f5cbdf 100644 (file)
@@ -157,3 +157,13 @@ void runAlwaysWarnWithArg(int a) {
 // Bug: we would complain about `a` being undeclared if this was spelled
 // __diagnose_if__.
 void underbarName(int a) __attribute__((__diagnose_if__(a, "", "warning")));
+
+// PR38095
+void constCharStar(const char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}}
+void charStar(char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}}
+void runConstCharStar() {
+  constCharStar("foo");
+  charStar("bar");
+  constCharStar(""); // expected-error {{empty string not allowed}}
+  charStar(""); // expected-error {{empty string not allowed}}
+}