[cfe-commits] r146371 - in /cfe/trunk: include/clang/Basic/DiagnosticASTKinds.td lib/AST/ExprConstant.cpp test/SemaCXX/constant-expression-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Dec 12 04:46:16 PST 2011


Author: rsmith
Date: Mon Dec 12 06:46:16 2011
New Revision: 146371

URL: http://llvm.org/viewvc/llvm-project?rev=146371&view=rev
Log:
Implement C++11 constant expression cast restrictions.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=146371&r1=146370&r2=146371&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Mon Dec 12 06:46:16 2011
@@ -12,6 +12,9 @@
 //def note_comma_in_ice : Note<
 //  "C does not permit evaluated commas in an integer constant expression">;
 def note_expr_divide_by_zero : Note<"division by zero">;
+def note_constexpr_invalid_cast : Note<
+  "%select{reinterpret_cast|dynamic_cast|reinterpreting cast}0 not allowed "
+  "in a constant expression">;
 
 // inline asm related.
 let CategoryName = "Inline Assembly Issue" in {

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=146371&r1=146370&r2=146371&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Dec 12 06:46:16 2011
@@ -1616,6 +1616,15 @@
   RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
     { return StmtVisitorTy::Visit(E->getExpr()); }
 
+  RetTy VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) {
+    CCEDiag(E, diag::note_constexpr_invalid_cast) << 0;
+    return static_cast<Derived*>(this)->VisitCastExpr(E);
+  }
+  RetTy VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
+    CCEDiag(E, diag::note_constexpr_invalid_cast) << 1;
+    return static_cast<Derived*>(this)->VisitCastExpr(E);
+  }
+
   RetTy VisitBinaryOperator(const BinaryOperator *E) {
     switch (E->getOpcode()) {
     default:
@@ -1988,6 +1997,7 @@
       return LValueExprEvaluatorBaseTy::VisitCastExpr(E);
 
     case CK_LValueBitCast:
+      this->CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
       if (!Visit(E->getSubExpr()))
         return false;
       Result.Designator.setInvalid();
@@ -2213,6 +2223,11 @@
   case CK_CPointerToObjCPointerCast:
   case CK_BlockPointerToObjCPointerCast:
   case CK_AnyPointerToBlockPointerCast:
+    // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are
+    // 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())
+      CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
     if (!Visit(SubExpr))
       return false;
     Result.Designator.setInvalid();
@@ -2251,6 +2266,8 @@
     return ValueInitialization(E);
 
   case CK_IntegralToPointer: {
+    CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
+
     CCValue Value;
     if (!EvaluateIntegerOrLValue(SubExpr, Value, Info))
       break;
@@ -3826,6 +3843,8 @@
   }
 
   case CK_PointerToIntegral: {
+    CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
+
     LValue LV;
     if (!EvaluatePointer(SubExpr, LV, Info))
       return false;

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=146371&r1=146370&r2=146371&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Mon Dec 12 06:46:16 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i686-linux -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple i686-linux -fsyntax-only -verify -std=c++11 -pedantic %s -Wno-comment
 
 namespace StaticAssertFoldTest {
 
@@ -165,7 +165,7 @@
   constexpr int f() { return 1; }
   typedef double (*DoubleFn)();
   typedef int (*IntFn)();
-  int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}}
+  int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}} expected-warning{{extension}}
   int b[(int)IntFn(f)()];    // ok
 }
 
@@ -297,6 +297,31 @@
 // test elsewhere.
 constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr);
 
+struct Str {
+  // FIXME: In C++ mode, we should say 'integral' not 'integer'
+  int a : dynamic_cast<S*>(sptr) == dynamic_cast<S*>(sptr); // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{dynamic_cast not allowed in a constant expression}}
+  int b : reinterpret_cast<S*>(sptr) == reinterpret_cast<S*>(sptr); // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{reinterpret_cast not allowed in a constant expression}}
+  int c : (S*)(long)(sptr) == (S*)(long)(sptr); // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{reinterpreting cast not allowed in a constant expression}}
+  int d : (S*)(42) == (S*)(42); // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{reinterpreting cast not allowed in a constant expression}}
+  int e : (Str*)(sptr) == (Str*)(sptr); // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{reinterpreting cast not allowed in a constant expression}}
+  int f : &(Str&)(*sptr) == &(Str&)(*sptr); // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{reinterpreting cast not allowed in a constant expression}}
+  int g : (S*)(void*)(sptr) == sptr; // \
+    expected-warning {{not integer constant expression}} \
+    expected-note {{reinterpreting cast not allowed in a constant expression}}
+};
+
 extern char externalvar[];
 // FIXME: This is not a constant expression; check we reject this and move this
 // test elsewhere.
@@ -414,7 +439,7 @@
 static_assert(**(**(zs + 1) + 1) == 11, "");
 static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, "");
 
-constexpr int arr[40] = { 1, 2, 3, [8] = 4 };
+constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; // expected-warning {{extension}}
 constexpr int SumNonzero(const int *p) {
   return *p + (*p ? SumNonzero(p+1) : 0);
 }
@@ -677,7 +702,7 @@
   int b;
 };
 
-constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } };
+constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; // expected-warning 4{{extension}}
 static_assert(u[0].a == 0, "");
 static_assert(u[0].b, ""); // expected-error {{constant expression}}
 static_assert(u[1].b == 1, "");





More information about the cfe-commits mailing list