In C++11 mode, when an integral constant expression is desired and we have a
value of class type, look for a unique conversion operator converting to
integral or unscoped enumeration type and use that. Implements [expr.const]p5.
Sema::VerifyIntegerConstantExpression now performs the conversion and returns
the converted result. Some important callers of Expr::isIntegralConstantExpr
have been switched over to using it (including all of those required for C++11
conformance); this switch brings a side-benefit of improved diagnostics and, in
several cases, simpler code. However, some language extensions and attributes
have not been moved across and will not perform implicit conversions on
constant expressions of literal class type where an ICE is required.
In passing, fix static_assert to perform a contextual conversion to bool on its
argument.
llvm-svn: 149776
diff --git a/clang/test/CXX/except/except.spec/p1.cpp b/clang/test/CXX/except/except.spec/p1.cpp
index a6e7850..c68ec56 100644
--- a/clang/test/CXX/except/except.spec/p1.cpp
+++ b/clang/test/CXX/except/except.spec/p1.cpp
@@ -74,7 +74,7 @@
namespace PR11084 {
template<int X> struct A {
- static int f() noexcept(1/X) { return 10; } // expected-error{{argument to noexcept specifier must be a constant expression}}
+ static int f() noexcept(1/X) { return 10; } // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}}
};
void g() { A<0>::f(); } // expected-note{{in instantiation of template class 'PR11084::A<0>' requested here}}
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 0b22151..ac759cb 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -268,12 +268,14 @@
// non-volatile const object with a preceding initialization, initialized
// with a constant expression [Note: a string literal (2.14.5 [lex.string])
// corresponds to an array of such objects. -end note], or
- volatile const int vi = 1; // expected-note {{here}}
+ volatile const int vi = 1; // expected-note 2{{here}}
const int ci = 1;
volatile const int &vrci = ci;
- static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}}
+ static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}}
static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}}
- static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+ static_assert(vrci, ""); // ok, vrci is converted to a prvalue before
+ // evaluation and loses its volatility in the
+ // conversion.
// - a non-volatile glvalue of literal type that refers to a non-volatile
// object defined with constexpr, or that refers to a sub-object of such an
@@ -282,23 +284,23 @@
constexpr S(int=0) : i(1), v(1) {}
constexpr S(const S &s) : i(2), v(2) {}
int i;
- volatile int v;
+ volatile int v; // expected-note {{here}}
};
constexpr S s;
- constexpr volatile S vs; // expected-note {{here}}
+ constexpr volatile S vs; // expected-note 2{{here}}
constexpr const volatile S &vrs = s;
static_assert(s.i, "");
- static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
- static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+ static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile member 'v'}}
+ static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}}
static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}}
- static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+ static_assert(vrs.i, ""); // ok
// - a non-volatile glvalue of literal type that refers to a non-volatile
// temporary object whose lifetime has not ended, initialized with a
// constant expression;
constexpr volatile S f() { return S(); }
static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here!
- static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+ static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}}
}
// DR1312: The proposed wording for this defect has issues, so we ignore this
@@ -385,7 +387,7 @@
int k;
typedef int I;
struct T {
- int n : (k.~I(), 0); // expected-error {{constant expression}} expected-note{{subexpression}}
+ int n : (k.~I(), 0); // expected-error {{constant expression}}
};
}
@@ -419,8 +421,8 @@
namespace NewDelete {
int *p = 0;
struct T {
- int n : *new int(4); // expected-error {{constant expression}} expected-note {{subexpression}}
- int m : (delete p, 2); // expected-error {{constant expression}} expected-note {{subexpression}}
+ int n : *new int(4); // expected-error {{constant expression}}
+ int m : (delete p, 2); // expected-error {{constant expression}}
};
}
@@ -540,7 +542,7 @@
// - a throw-expression (15.1)
namespace Throw {
struct S {
- int n : (throw "hello", 10); // expected-error {{constant expression}} expected-note {{subexpression}}
+ int n : (throw "hello", 10); // expected-error {{constant expression}}
};
}
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index ff9118a..198da77 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -24,7 +24,7 @@
};
extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
[[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}
-[[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}}
+[[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}} expected-note {{declared here}}
[[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}}
[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
@@ -33,7 +33,7 @@
// Argument tests
alignas int aligned_no_params; // expected-error {{expected '('}}
-alignas(i) int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}}
+alignas(i) int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}} expected-note {{read of non-const variable 'i'}}
// Statement tests
void foo () {
diff --git a/clang/test/Sema/i-c-e.c b/clang/test/Sema/i-c-e.c
index a25bc1f..ee61ac3 100644
--- a/clang/test/Sema/i-c-e.c
+++ b/clang/test/Sema/i-c-e.c
@@ -19,9 +19,9 @@
char b[__builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+2.0) : -1];
struct c {
- int a : ( // expected-error {{expression is not an integer constant expression}}
+ int a : (
__builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+
- expr // expected-note {{subexpression not valid in a constant expression}}
+ expr // expected-error {{expression is not an integer constant expression}}
) : -1);
};
diff --git a/clang/test/Sema/switch.c b/clang/test/Sema/switch.c
index 2dc965f..ea9be59 100644
--- a/clang/test/Sema/switch.c
+++ b/clang/test/Sema/switch.c
@@ -50,12 +50,15 @@
}
switch (cond) {
- case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in a constant expression}}
+ case g() // expected-error {{expression is not an integer constant expression}}
+ && 0:
break;
}
switch (cond) {
- case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in a constant expression}}
+ case 0 ...
+ g() // expected-error {{expression is not an integer constant expression}}
+ || 1:
break;
}
}
diff --git a/clang/test/SemaCXX/enum-bitfield.cpp b/clang/test/SemaCXX/enum-bitfield.cpp
index 831b982..63445ca 100644
--- a/clang/test/SemaCXX/enum-bitfield.cpp
+++ b/clang/test/SemaCXX/enum-bitfield.cpp
@@ -14,5 +14,5 @@
struct Y {
enum E : int(2);
- enum E : Z(); // expected-error{{not an integral constant}}
+ enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}}
};
diff --git a/clang/test/SemaCXX/i-c-e-cxx.cpp b/clang/test/SemaCXX/i-c-e-cxx.cpp
index 0bfd221..5631577 100644
--- a/clang/test/SemaCXX/i-c-e-cxx.cpp
+++ b/clang/test/SemaCXX/i-c-e-cxx.cpp
@@ -60,9 +60,9 @@
// This isn't an integral constant expression, but make sure it folds anyway.
struct PR8836 { char _; long long a; }; // expected-warning {{long long}}
-int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}}
+int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
-const int nonconst = 1.0;
-int arr[nonconst]; // expected-warning {{folded to constant array as an extension}}
+const int nonconst = 1.0; // expected-note {{declared here}}
+int arr[nonconst]; // expected-warning {{folded to constant array as an extension}} expected-note {{initializer of 'nonconst' is not a constant expression}}
const int castfloat = static_cast<int>(1.0);
int arr2[castfloat]; // ok
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 45d4f3d..4daa65e 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -61,13 +61,13 @@
void bad_news(int *ip)
{
- int i = 1;
+ int i = 1; // expected-note 2{{here}}
(void)new; // expected-error {{expected a type}}
(void)new 4; // expected-error {{expected a type}}
(void)new () int; // expected-error {{expected expression}}
(void)new int[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}}
- (void)new int[1][i]; // expected-error {{only the first dimension}}
- (void)new (int[1][i]); // expected-error {{only the first dimension}}
+ (void)new int[1][i]; // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
+ (void)new (int[1][i]); // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
(void)new (int[i]); // expected-warning {{when type is in parentheses}}
(void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}}
(void)new int(1, 2); // expected-error {{excess elements in scalar initializer}}