aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp')
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp170
1 files changed, 155 insertions, 15 deletions
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
index 06993c225e..9361642326 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -verify -std=c++11 %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
namespace N {
typedef char C;
@@ -8,7 +9,7 @@ namespace M {
typedef double D;
}
-struct NonLiteral { // expected-note 2{{no constexpr constructors}}
+struct NonLiteral { // expected-note 3{{no constexpr constructors}}
NonLiteral() {}
NonLiteral(int) {}
};
@@ -37,7 +38,10 @@ struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-li
// - its return type shall be a literal type;
constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
- constexpr void VoidReturn() const { return; } // expected-error {{constexpr function's return type 'void' is not a literal type}}
+ constexpr void VoidReturn() const { return; }
+#ifndef CXX1Y
+ // expected-error@-2 {{constexpr function's return type 'void' is not a literal type}}
+#endif
constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}}
typedef NonLiteral F() const;
constexpr F NonLiteralReturn2; // ok until definition
@@ -49,12 +53,17 @@ struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-li
// - its function-body shall be = delete, = default,
constexpr int Deleted() const = delete;
- // It's not possible for the function-body to legally be "= default" here.
+ // It's not possible for the function-body to legally be "= default" here
+ // (that is, for a non-constructor function) in C++11.
// Other than constructors, only the copy- and move-assignment operators and
// destructor can be defaulted. Destructors can't be constexpr since they
// don't have a literal return type. Defaulted assignment operators can't be
// constexpr since they can't be const.
- constexpr T &operator=(const T&) = default; // expected-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} expected-warning {{C++1y}}
+ constexpr T &operator=(const T&) = default;
+#ifndef CXX1Y
+ // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
+ // expected-warning@-3 {{C++1y}}
+#endif
};
struct U {
constexpr U SelfReturn() const;
@@ -65,8 +74,8 @@ struct V : virtual U { // expected-note {{here}}
constexpr int F() const { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}}
};
-// or a compound-statememt that contains only
-constexpr int AllowedStmts() {
+// or a compound-statememt that contains only [CXX11]
+constexpr int AllowedStmtsCXX11() {
// - null statements
;
@@ -91,34 +100,122 @@ constexpr int AllowedStmts() {
// - and exactly one return statement
return sizeof(K) + sizeof(C) + sizeof(K);
}
+
+// or a compound-statement that does not contain [CXX1Y]
+constexpr int DisallowedStmtsCXX1Y_1() {
+ // - an asm-definition
+ asm("int3"); // expected-error {{statement not allowed in constexpr function}}
+ return 0;
+}
+constexpr int DisallowedStmtsCXX1Y_2() {
+ // - a goto statement
+ goto x; // expected-error {{statement not allowed in constexpr function}}
+x:
+ return 0;
+}
+constexpr int DisallowedStmtsCXX1Y_3() {
+ // - a try-block,
+ try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
+ return 0;
+}
+constexpr int DisallowedStmtsCXX1Y_4() {
+ // - a definition of a variable of non-literal type
+ NonLiteral nl; // expected-error {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function}}
+ return 0;
+}
+constexpr int DisallowedStmtsCXX1Y_5() {
+ // - a definition of a variable of static storage duration
+ static constexpr int n = 123; // expected-error {{static variable not permitted in a constexpr function}}
+ return n;
+}
+constexpr int DisallowedStmtsCXX1Y_6() {
+ // - a definition of a variable of thread storage duration
+ thread_local constexpr int n = 123; // expected-error {{thread_local variable not permitted in a constexpr function}}
+ return n;
+}
+constexpr int DisallowedStmtsCXX1Y_7() {
+ // - a definition of a variable for which no initialization is performed
+ int n; // expected-error {{variables defined in a constexpr function must be initialized}}
+ return 0;
+}
+
constexpr int ForStmt() {
- for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr function}}
+ for (int n = 0; n < 10; ++n)
+#ifndef CXX1Y
+ // expected-error@-2 {{statement not allowed in constexpr function}}
+#else
+ // FIXME: Once we support evaluating a for-statement, this diagnostic should disappear.
+ // expected-error@-6 {{never produces a constant expression}}
+ // expected-note@-6 {{subexpression}}
+#endif
return 0;
}
constexpr int VarDecl() {
- constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr function}}
+ int a = 0;
+#ifndef CXX1Y
+ // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
+#endif
+ return 0;
+}
+constexpr int ConstexprVarDecl() {
+ constexpr int a = 0;
+#ifndef CXX1Y
+ // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
+#endif
+ return 0;
+}
+constexpr int VarWithCtorDecl() {
+ Literal a;
+#ifndef CXX1Y
+ // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
+#endif
return 0;
}
+NonLiteral nl;
+constexpr NonLiteral &ExternNonLiteralVarDecl() {
+ extern NonLiteral nl;
+#ifndef CXX1Y
+ // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
+#endif
+ return nl;
+}
+static_assert(&ExternNonLiteralVarDecl() == &nl, "");
constexpr int FuncDecl() {
- constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr function}}
+ constexpr int ForwardDecl(int);
+#ifndef CXX1Y
+ // expected-error@-2 {{use of this statement in a constexpr function is a C++1y extension}}
+#endif
return ForwardDecl(42);
}
constexpr int ClassDecl1() {
- typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr function}}
+ typedef struct { } S1;
+#ifndef CXX1Y
+ // expected-error@-2 {{type definition in a constexpr function is a C++1y extension}}
+#endif
return 0;
}
constexpr int ClassDecl2() {
- using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr function}}
+ using S2 = struct { };
+#ifndef CXX1Y
+ // expected-error@-2 {{type definition in a constexpr function is a C++1y extension}}
+#endif
return 0;
}
constexpr int ClassDecl3() {
- struct S3 { }; // expected-error {{types cannot be defined in a constexpr function}}
+ struct S3 { };
+#ifndef CXX1Y
+ // expected-error@-2 {{type definition in a constexpr function is a C++1y extension}}
+#endif
return 0;
}
constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}}
constexpr int MultiReturn() {
- return 0; // expected-note {{return statement}}
- return 0; // expected-error {{multiple return statements in constexpr function}}
+ return 0;
+ return 0;
+#ifndef CXX1Y
+ // expected-error@-2 {{multiple return statements in constexpr function}}
+ // expected-note@-4 {{return statement}}
+#endif
}
// - every constructor call and implicit conversion used in initializing the
@@ -153,3 +250,46 @@ namespace rdar13584715 {
}
}
}
+
+namespace std_example {
+ constexpr int square(int x) {
+ return x * x;
+ }
+ constexpr long long_max() {
+ return 2147483647;
+ }
+ constexpr int abs(int x) {
+ if (x < 0)
+#ifndef CXX1Y
+ // expected-error@-2 {{C++1y}}
+#endif
+ x = -x;
+ return x;
+ }
+ constexpr int first(int n) {
+ static int value = n; // expected-error {{static variable not permitted}}
+ return value;
+ }
+ constexpr int uninit() {
+ int a; // expected-error {{must be initialized}}
+ return a;
+ }
+ // FIXME: Once we support variable mutation, this can produce a
+ // constant expression.
+ constexpr int prev(int x) { // expected-error {{never produces a constant expression}}
+ return --x; // expected-note {{subexpression}}
+ }
+ constexpr int g(int x, int n) {
+ int r = 1;
+ while (--n > 0) r *= x;
+ return r;
+ }
+#ifndef CXX1Y
+ // expected-error@-5 {{C++1y}}
+ // expected-error@-5 {{statement not allowed}}
+#else
+ // FIXME: This should be allowed.
+ // expected-error@-10 {{never produces a constant}}
+ // expected-note@-9 {{subexpression}}
+#endif
+}