r179969 - The 'constexpr implies const' rule for non-static member functions is gone in

Richard Smith richard-llvm at metafoo.co.uk
Sat Apr 20 18:08:50 PDT 2013


Author: rsmith
Date: Sat Apr 20 20:08:50 2013
New Revision: 179969

URL: http://llvm.org/viewvc/llvm-project?rev=179969&view=rev
Log:
The 'constexpr implies const' rule for non-static member functions is gone in
C++1y, so stop adding the 'const' there. Provide a compatibility warning for
code relying on this in C++11, with a fix-it hint. Update our lazily-written
tests to add the const, except for those ones which were testing our
implementation of this rule.

Added:
    cfe/trunk/test/FixIt/fixit-cxx1y-compat.cpp
    cfe/trunk/test/SemaCXX/cxx1y-constexpr-not-const.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/CXX/basic/basic.types/p10.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp
    cfe/trunk/test/CXX/dcl.dcl/p4-0x.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
    cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp
    cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
    cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp
    cfe/trunk/test/CXX/expr/expr.const/p5-0x.cpp
    cfe/trunk/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
    cfe/trunk/test/Parser/cxx0x-ambig.cpp
    cfe/trunk/test/Parser/cxx0x-decl.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
    cfe/trunk/test/SemaCXX/enum-unscoped-nonexistent.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Apr 20 20:08:50 2013
@@ -1550,6 +1550,11 @@ def note_for_range_begin_end : Note<
 def warn_cxx98_compat_constexpr : Warning<
   "'constexpr' specifier is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
+// FIXME: Maybe this should also go in -Wc++1y-compat?
+def warn_cxx1y_compat_constexpr_not_const : Warning<
+  "'constexpr' non-static member function will not be implicitly 'const' "
+  "in C++1y; add 'const' to avoid a change in behavior">,
+  InGroup<DiagGroup<"constexpr-not-const">>;
 def err_invalid_constexpr : Error<
   "%select{function parameter|typedef|non-static data member}0 "
   "cannot be constexpr">;

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Apr 20 20:08:50 2013
@@ -5015,7 +5015,8 @@ void Parser::ParseFunctionDeclarator(Dec
       Sema::CXXThisScopeRAII ThisScope(Actions,
                                dyn_cast<CXXRecordDecl>(Actions.CurContext),
                                DS.getTypeQualifiers() |
-                               (D.getDeclSpec().isConstexprSpecified()
+                               (D.getDeclSpec().isConstexprSpecified() &&
+                                !getLangOpts().CPlusPlus1y
                                   ? Qualifiers::Const : 0),
                                IsCXX11MemberFunction);
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 20 20:08:50 2013
@@ -6726,9 +6726,12 @@ bool Sema::CheckFunctionDeclaration(Scop
   //
   // This needs to be delayed until we know whether this is an out-of-line
   // definition of a static member function.
+  //
+  // This rule is not present in C++1y, so we produce a backwards
+  // compatibility warning whenever it happens in C++11.
   CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
-  if (MD && MD->isConstexpr() && !MD->isStatic() &&
-      !isa<CXXConstructorDecl>(MD) &&
+  if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
+      !MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
       (MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
     CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
     if (FunctionTemplateDecl *OldTD =
@@ -6743,6 +6746,18 @@ bool Sema::CheckFunctionDeclaration(Scop
                                       ArrayRef<QualType>(FPT->arg_type_begin(),
                                                          FPT->getNumArgs()),
                                           EPI));
+
+      // Warn that we did this, if we're not performing template instantiation.
+      // In that case, we'll have warned already when the template was defined.
+      if (ActiveTemplateInstantiations.empty()) {
+        SourceLocation AddConstLoc;
+        if (FunctionTypeLoc FTL = MD->getTypeSourceInfo()->getTypeLoc()
+                .IgnoreParens().getAs<FunctionTypeLoc>())
+          AddConstLoc = PP.getLocForEndOfToken(FTL.getRParenLoc());
+
+        Diag(MD->getLocation(), diag::warn_cxx1y_compat_constexpr_not_const)
+          << FixItHint::CreateInsertion(AddConstLoc, " const");
+      }
     }
   }
 

Modified: cfe/trunk/test/CXX/basic/basic.types/p10.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.types/p10.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.types/p10.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.types/p10.cpp Sat Apr 20 20:08:50 2013
@@ -32,13 +32,13 @@ constexpr ClassTemp<int> classtemplate2[
 
 //  - it has a trivial destructor
 struct UserProvDtor {
-  constexpr int f(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}}
+  constexpr int f() const; // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}}
   ~UserProvDtor(); // expected-note {{has a user-provided destructor}}
 };
 
 struct NonTrivDtor {
   constexpr NonTrivDtor();
-  constexpr int f(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}}
+  constexpr int f() const; // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}}
   virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
 };
 struct NonTrivDtorBase {
@@ -71,11 +71,11 @@ struct CtorTemplate {
 };
 struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
   constexpr CopyCtorOnly(CopyCtorOnly&);
-  constexpr int f(); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}}
+  constexpr int f() const; // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}}
 };
 struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
   constexpr MoveCtorOnly(MoveCtorOnly&&);
-  constexpr int f(); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}}
+  constexpr int f() const; // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}}
 };
 template<typename T>
 struct CtorArg {
@@ -104,7 +104,7 @@ constexpr int f(NonLitMember) {} // expe
 struct NonLitBase :
   S { // expected-note {{base class 'S' of non-literal type}}
   constexpr NonLitBase();
-  constexpr int f() { return 0; } // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}}
+  constexpr int f() const { return 0; } // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}}
 };
 struct LitMemBase : Agg {
   Agg agg;

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Sat Apr 20 20:08:50 2013
@@ -71,7 +71,7 @@ struct ConstexprDtor {
 template <typename T> constexpr T ft(T t) { return t; }
 template <typename T> T gt(T t) { return t; }
 struct S {
-  template<typename T> constexpr T f();
+  template<typename T> constexpr T f(); // expected-warning {{C++1y}}
   template<typename T> T g() const;
 };
 
@@ -81,7 +81,7 @@ template <> char ft(char c) { return c;
 template <> constexpr char ft(char nl); // expected-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}}
 template <> constexpr int gt(int nl) { return nl; }
 template <> notlit S::f() const { return notlit(); }
-template <> constexpr int S::g() { return 0; } // expected-note {{previous}}
+template <> constexpr int S::g() { return 0; } // expected-note {{previous}} expected-warning {{C++1y}}
 template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}}
 // specializations can drop the 'constexpr' but not the implied 'const'.
 template <> char S::g() { return 0; } // expected-error {{no function template matches}}

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp Sat Apr 20 20:08:50 2013
@@ -28,41 +28,41 @@ struct SS : S {
 // constraints:
 struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}}
   constexpr T();
-  constexpr int f(); // expected-error {{non-literal type 'T' cannot have constexpr members}}
+  constexpr int f() const; // expected-error {{non-literal type 'T' cannot have constexpr members}}
 
   //  - it shall not be virtual;
-  virtual constexpr int ExplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}}
+  virtual constexpr int ExplicitlyVirtual() const { return 0; } // expected-error {{virtual function cannot be constexpr}}
 
-  constexpr int ImplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}}
+  constexpr int ImplicitlyVirtual() const { return 0; } // expected-error {{virtual function cannot be constexpr}}
 
   //  - its return type shall be a literal type;
-  constexpr NonLiteral NonLiteralReturn() { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
-  constexpr void VoidReturn() { return; } // expected-error {{constexpr function's return type 'void' is not 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 ~T(); // expected-error {{destructor cannot be marked constexpr}}
-  typedef NonLiteral F();
+  typedef NonLiteral F() const;
   constexpr F NonLiteralReturn2; // ok until definition
 
   //  - each of its parameter types shall be a literal type;
-  constexpr int NonLiteralParam(NonLiteral) { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
-  typedef int G(NonLiteral);
+  constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
+  typedef int G(NonLiteral) const;
   constexpr G NonLiteralParam2; // ok until definition
 
   //  - its function-body shall be = delete, = default,
-  constexpr int Deleted() = delete;
+  constexpr int Deleted() const = delete;
   // It's not possible for the function-body to legally be "= default" here.
   // 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}}
+  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}}
 };
 struct U {
-  constexpr U SelfReturn();
-  constexpr int SelfParam(U);
+  constexpr U SelfReturn() const;
+  constexpr int SelfParam(U) const;
 };
 
 struct V : virtual U { // expected-note {{here}}
-  constexpr int F() { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}}
+  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

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp Sat Apr 20 20:08:50 2013
@@ -102,7 +102,7 @@ X x = cmin(X(), X()); // ok, not constex
 template<typename T>
 struct Y {
   constexpr Y() {}
-  constexpr int get() { return T(); }
+  constexpr int get() { return T(); } // expected-warning {{C++1y}}
 };
 struct Z { operator int(); };
 

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp Sat Apr 20 20:08:50 2013
@@ -24,7 +24,7 @@ struct S {
 struct T {};
 
 template<typename T> struct ImplicitVirtualFromDependentBase : T {
-  constexpr int ImplicitlyVirtual() { return 0; }
+  constexpr int ImplicitlyVirtual() const { return 0; }
 };
 
 constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate virtual function call}}
@@ -32,7 +32,7 @@ constexpr int b = ImplicitVirtualFromDep
 constexpr int c = ImplicitVirtualFromDependentBase<S>().ImplicitVirtualFromDependentBase<S>::ImplicitlyVirtual();
 
 template<typename R> struct ConstexprMember {
-  constexpr R F() { return 0; }
+  constexpr R F() const { return 0; }
 };
 constexpr int d = ConstexprMember<int>().F(); // ok
 constexpr int e = ConstexprMember<NonLiteral>().F(); // expected-error {{constant expression}}

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp Sat Apr 20 20:08:50 2013
@@ -3,13 +3,13 @@
 using size_t = decltype(sizeof(int));
 
 struct S {
-  constexpr int f();
+  constexpr int f(); // expected-warning {{C++1y}}
   constexpr int g() const;
-  constexpr int h();
+  constexpr int h(); // expected-warning {{C++1y}}
   int h();
   static constexpr int Sf();
   /*static*/ constexpr void *operator new(size_t) noexcept;
-  template<typename T> constexpr T tm();
+  template<typename T> constexpr T tm(); // expected-warning {{C++1y}}
   template<typename T> static constexpr T ts();
 };
 
@@ -26,12 +26,12 @@ void f(const S &s) {
 }
 
 constexpr int S::f() const { return 0; }
-constexpr int S::g() { return 1; }
-constexpr int S::h() { return 0; }
+constexpr int S::g() { return 1; } // expected-warning {{C++1y}}
+constexpr int S::h() { return 0; } // expected-warning {{C++1y}}
 int S::h() { return 0; }
 constexpr int S::Sf() { return 2; }
 constexpr void *S::operator new(size_t) noexcept { return 0; }
-template<typename T> constexpr T S::tm() { return T(); }
+template<typename T> constexpr T S::tm() { return T(); } // expected-warning {{C++1y}}
 template<typename T> constexpr T S::ts() { return T(); }
 
 namespace std_example {
@@ -39,7 +39,7 @@ namespace std_example {
   class debug_flag { // expected-note {{not an aggregate and has no constexpr constructors}}
   public:
     explicit debug_flag(bool);
-    constexpr bool is_on(); // expected-error {{non-literal type 'std_example::debug_flag' cannot have constexpr members}}
+    constexpr bool is_on() const; // expected-error {{non-literal type 'std_example::debug_flag' cannot have constexpr members}}
   private:
     bool flag;
   };

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp Sat Apr 20 20:08:50 2013
@@ -76,7 +76,7 @@ namespace libcxx_example {
   template<typename T> struct swappable {
     typedef decltype(swap(declval<T&>(), declval<T&>())) type;
     static const bool value = !is_same<type, nat>::value;
-    constexpr operator bool() { return value; }
+    constexpr operator bool() const { return value; }
   };
 
   static_assert(swappable<int>(), "");

Modified: cfe/trunk/test/CXX/dcl.dcl/p4-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/p4-0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/p4-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/p4-0x.cpp Sat Apr 20 20:08:50 2013
@@ -2,15 +2,15 @@
 
 struct S {
   constexpr S(bool b) : b(b) {}
-  constexpr explicit operator bool() { return b; }
+  constexpr explicit operator bool() const { return b; }
   bool b;
 };
 struct T {
-  constexpr operator int() { return 1; }
+  constexpr operator int() const { return 1; }
 };
 struct U {
-  constexpr operator int() { return 1; } // expected-note {{candidate}}
-  constexpr operator long() { return 0; } // expected-note {{candidate}}
+  constexpr operator int() const { return 1; } // expected-note {{candidate}}
+  constexpr operator long() const { return 0; } // expected-note {{candidate}}
 };
 
 static_assert(S(true), "");

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp Sat Apr 20 20:08:50 2013
@@ -6,8 +6,8 @@ struct S1 {
   constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
   constexpr S1(const S1&) = default;
   constexpr S1(S1&&) = default;
-  constexpr S1 &operator=(const S1&) = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}}
-  constexpr S1 &operator=(S1&&) = default; // expected-error {{explicitly-defaulted move assignment operator may not have}}
+  constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}}
+  constexpr S1 &operator=(S1&&) const = default; // expected-error {{explicitly-defaulted move assignment operator may not have}}
   constexpr ~S1() = default; // expected-error {{destructor cannot be marked constexpr}}
   int n;
 };

Modified: cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.ass/p9-cxx11.cpp Sat Apr 20 20:08:50 2013
@@ -24,8 +24,8 @@ struct S {
   int a, b;
 };
 struct T {
-  constexpr int operator=(S s) { return s.a; }
-  constexpr int operator+=(S s) { return s.b; }
+  constexpr int operator=(S s) const { return s.a; }
+  constexpr int operator+=(S s) const { return s.b; }
 };
 static_assert((T() = {4, 9}) == 4, "");
 static_assert((T() += {4, 9}) == 9, "");

Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Sat Apr 20 20:08:50 2013
@@ -118,7 +118,7 @@ namespace IncompleteClassTypeAddr {
   constexpr S (*p2)[] = &sArr; // ok
 
   struct S {
-    constexpr S *operator&() { return nullptr; }
+    constexpr S *operator&() const { return nullptr; }
   };
   constexpr S *q = &s; // ok
   static_assert(!q, "");
@@ -205,7 +205,7 @@ namespace UndefinedBehavior {
     constexpr const int &np = (*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot access array element of null pointer}}
 
     struct C {
-      constexpr int f() { return 0; }
+      constexpr int f() const { return 0; }
     } constexpr c = C();
     constexpr int k1 = c.f(); // ok
     constexpr int k2 = ((C*)nullptr)->f(); // expected-error {{constant expression}} expected-note {{cannot call member function on null pointer}}
@@ -481,14 +481,14 @@ namespace UnspecifiedRelations {
   public:
     constexpr A() : a(0), b(0) {}
     int a;
-    constexpr bool cmp() { return &a < &b; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'A' with differing access specifiers (public vs private) has unspecified value}}
+    constexpr bool cmp() const { return &a < &b; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'A' with differing access specifiers (public vs private) has unspecified value}}
   private:
     int b;
   };
   class B {
   public:
     A a;
-    constexpr bool cmp() { return &a.a < &b.a; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'B' with differing access specifiers (public vs protected) has unspecified value}}
+    constexpr bool cmp() const { return &a.a < &b.a; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'B' with differing access specifiers (public vs protected) has unspecified value}}
   protected:
     A b;
   };

Modified: cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp Sat Apr 20 20:08:50 2013
@@ -101,7 +101,7 @@ int n = Val<bool, &S::operator int>::val
 
 namespace NonConstLValue {
   struct S {
-    constexpr operator int() { return 10; }
+    constexpr operator int() const { return 10; }
   };
   S s; // not constexpr
   // Under the FDIS, this is not a converted constant expression.

Modified: cfe/trunk/test/CXX/expr/expr.const/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p5-0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p5-0x.cpp Sat Apr 20 20:08:50 2013
@@ -7,8 +7,8 @@ namespace std_example {
 
 struct A {
   constexpr A(int i) : val(i) { }
-  constexpr operator int() { return val; }
-  constexpr operator long() { return 43; }
+  constexpr operator int() const { return val; }
+  constexpr operator long() const { return 43; }
 private:
   int val;
 };
@@ -21,17 +21,17 @@ int ary[a]; // expected-error {{size of
 
 struct OK {
   constexpr OK() {}
-  constexpr operator int() { return 8; }
+  constexpr operator int() const { return 8; }
 } constexpr ok;
 extern struct Incomplete incomplete; // expected-note 4{{forward decl}}
 struct Explicit {
   constexpr Explicit() {}
-  constexpr explicit operator int() { return 4; } // expected-note 4{{here}}
+  constexpr explicit operator int() const { return 4; } // expected-note 4{{here}}
 } constexpr expl;
 struct Ambiguous {
   constexpr Ambiguous() {}
-  constexpr operator int() { return 2; } // expected-note 4{{here}}
-  constexpr operator long() { return 1; } // expected-note 4{{here}}
+  constexpr operator int() const { return 2; } // expected-note 4{{here}}
+  constexpr operator long() const { return 1; } // expected-note 4{{here}}
 } constexpr ambig;
 
 constexpr int test_ok = ok; // ok

Modified: cfe/trunk/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp Sat Apr 20 20:08:50 2013
@@ -3,12 +3,12 @@
 
 struct Value {
   constexpr Value(int n) : n(n) {}
-  constexpr operator short() { return n; }
+  constexpr operator short() const { return n; }
   int n;
 };
 enum E { E0, E1 };
 struct Alt {
-  constexpr operator E() { return E0; }
+  constexpr operator E() const { return E0; }
 };
 
 constexpr short s = Alt();

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp Sat Apr 20 20:08:50 2013
@@ -193,18 +193,18 @@ namespace PacksAtDifferentLevels {
     template<typename...A>
     struct X6 {
       template<typename...B>
-      constexpr auto f1(A ...a) -> decltype(g(A(a + B())...)) { return g(A(a + B())...); }
+      constexpr auto f1(A ...a) const -> decltype(g(A(a + B())...)) { return g(A(a + B())...); }
 
       template<typename...B>
-      constexpr auto f2(A ...a, B ...b) -> decltype(g((&a)[b] ...)) { return g((&a)[b] ...); } // expected-note {{past-the-end}}
+      constexpr auto f2(A ...a, B ...b) const -> decltype(g((&a)[b] ...)) { return g((&a)[b] ...); } // expected-note {{past-the-end}}
 
       template<typename...B> struct Inner {
         template<typename...C>
-        constexpr auto f(A ...a, B ...b, C ...c) -> decltype(g(a+b+c...)) { return g(a+b+c...); }
+        constexpr auto f(A ...a, B ...b, C ...c) const -> decltype(g(a+b+c...)) { return g(a+b+c...); }
       };
     };
-    struct A { constexpr operator int() { return 2; } };
-    struct B { constexpr operator int() { return 1; } };
+    struct A { constexpr operator int() const { return 2; } };
+    struct B { constexpr operator int() const { return 1; } };
 
     static_assert(X6<unsigned char, int>().f1<A, B>(255, 1) == 12, "");
     static_assert(X6<int, int>().f2(3, 4, 0, 0) == 34, "");

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp Sat Apr 20 20:08:50 2013
@@ -9,7 +9,7 @@ template inline void X<int>::f(); // exp
 
 template<typename T>
 struct Y {
-  constexpr int f() { return 0; }
+  constexpr int f() { return 0; } // expected-warning{{C++1y}}
 };
 
 template constexpr int Y<int>::f() const; // expected-error{{explicit instantiation cannot be 'constexpr'}}

Added: cfe/trunk/test/FixIt/fixit-cxx1y-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx1y-compat.cpp?rev=179969&view=auto
==============================================================================
--- cfe/trunk/test/FixIt/fixit-cxx1y-compat.cpp (added)
+++ cfe/trunk/test/FixIt/fixit-cxx1y-compat.cpp Sat Apr 20 20:08:50 2013
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -x c++ -std=c++11 -fixit %t
+// RUN: %clang_cc1 -Wall -pedantic-errors -Werror -x c++ -std=c++11 %t
+// RUN: %clang_cc1 -Wall -pedantic-errors -Werror -x c++ -std=c++1y %t
+
+// This is a test of the code modification hints for C++1y-compatibility problems.
+
+struct S {
+  constexpr int &f(); // expected-warning {{'constexpr' non-static member function will not be implicitly 'const' in C++1y; add 'const' to avoid a change in behavior}}
+  int &f();
+};

Modified: cfe/trunk/test/Parser/cxx0x-ambig.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-ambig.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-ambig.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-ambig.cpp Sat Apr 20 20:08:50 2013
@@ -38,8 +38,8 @@ namespace bitfield {
     constexpr T() {}
     constexpr T(int) {}
     constexpr T(T, T, T, T) {}
-    constexpr T operator=(T) { return *this; }
-    constexpr operator int() { return 4; }
+    constexpr T operator=(T) const { return *this; }
+    constexpr operator int() const { return 4; }
   };
   constexpr T a, b, c, d;
 
@@ -68,7 +68,7 @@ namespace bitfield {
   };
 
   struct U {
-    constexpr operator T() { return T(); } // expected-note 2{{candidate}}
+    constexpr operator T() const { return T(); } // expected-note 2{{candidate}}
   };
   // This could be a bit-field.
   struct S7 {

Modified: cfe/trunk/test/Parser/cxx0x-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-decl.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-decl.cpp Sat Apr 20 20:08:50 2013
@@ -46,7 +46,7 @@ using PR14855 = int S::; // expected-err
 // a constexpr function.
 struct ConstexprTrailingReturn {
   int n;
-  constexpr auto f() -> decltype((n));
+  constexpr auto f() const -> decltype((n));
 };
 constexpr const int &ConstexprTrailingReturn::f() const { return n; }
 

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=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Sat Apr 20 20:08:50 2013
@@ -21,7 +21,7 @@ template<typename T, size_t N> constexpr
 template<typename T, size_t N> constexpr T *end(T (&xs)[N]) { return xs + N; }
 
 struct MemberZero {
-  constexpr int zero() { return 0; }
+  constexpr int zero() const { return 0; }
 };
 
 namespace DerivedToVBaseCast {
@@ -486,7 +486,7 @@ static_assert(CountZero(arr, arr + 40) =
 struct ArrayElem {
   constexpr ArrayElem() : n(0) {}
   int n;
-  constexpr int f() { return n; }
+  constexpr int f() const { return n; }
 };
 struct ArrayRVal {
   constexpr ArrayRVal() {}
@@ -731,14 +731,14 @@ namespace ConversionOperators {
 
 struct T {
   constexpr T(int n) : k(5*n - 3) {}
-  constexpr operator int() { return k; }
+  constexpr operator int() const { return k; }
   int k;
 };
 
 struct S {
   constexpr S(int n) : k(2*n + 1) {}
-  constexpr operator int() { return k; }
-  constexpr operator T() { return T(k); }
+  constexpr operator int() const { return k; }
+  constexpr operator T() const { return T(k); }
   int k;
 };
 
@@ -750,7 +750,7 @@ static_assert(check(S(5), 11), "");
 namespace PR14171 {
 
 struct X {
-  constexpr (operator int)() { return 0; }
+  constexpr (operator int)() const { return 0; }
 };
 static_assert(X() == 0, "");
 
@@ -764,13 +764,13 @@ namespace Temporaries {
 
 struct S {
   constexpr S() {}
-  constexpr int f();
+  constexpr int f() const;
 };
 struct T : S {
   constexpr T(int n) : S(), n(n) {}
   int n;
 };
-constexpr int S::f() {
+constexpr int S::f() const {
   // 'this' must be the postfix-expression in a class member access expression,
   // so we can't just use
   //   return static_cast<T*>(this)->n;
@@ -825,7 +825,7 @@ namespace MemberPointer {
   struct A {
     constexpr A(int n) : n(n) {}
     int n;
-    constexpr int f() { return n + 3; }
+    constexpr int f() const { return n + 3; }
   };
   constexpr A a(7);
   static_assert(A(5).*&A::n == 5, "");
@@ -836,7 +836,7 @@ namespace MemberPointer {
   struct B : A {
     constexpr B(int n, int m) : A(n), m(m) {}
     int m;
-    constexpr int g() { return n + m + 1; }
+    constexpr int g() const { return n + m + 1; }
   };
   constexpr B b(9, 13);
   static_assert(B(4, 11).*&A::n == 4, "");
@@ -857,7 +857,7 @@ namespace MemberPointer {
       m(m), n(n), pf(pf), pn(pn) {}
     constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {}
 
-    constexpr int f() { return this->*pn; }
+    constexpr int f() const { return this->*pn; }
     virtual int g() const;
 
     int m, n;
@@ -938,7 +938,7 @@ namespace ArrayBaseDerived {
   };
   struct Derived : Base {
     constexpr Derived() {}
-    constexpr const int *f() { return &n; }
+    constexpr const int *f() const { return &n; }
   };
 
   constexpr Derived a[10];
@@ -1038,7 +1038,7 @@ static_assert(makeComplexWrap(1,0) != co
 }
 
 namespace PR11595 {
-  struct A { constexpr bool operator==(int x) { return true; } };
+  struct A { constexpr bool operator==(int x) const { return true; } };
   struct B { B(); A& x; };
   static_assert(B().x == 3, "");  // expected-error {{constant expression}} expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}}
 

Added: cfe/trunk/test/SemaCXX/cxx1y-constexpr-not-const.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-constexpr-not-const.cpp?rev=179969&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-constexpr-not-const.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx1y-constexpr-not-const.cpp Sat Apr 20 20:08:50 2013
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+// RUN: %clang_cc1 -std=c++1y %s -verify -DCXX1Y
+
+struct X {
+  constexpr int f(); // @5
+  int f();           // @6
+};
+
+#ifdef CXX1Y
+// FIXME: Detect this situation and provide a better recovery.
+
+// expected-error at 6 {{class member cannot be redeclared}}
+// expected-note at 5 {{previous}}
+// expected-error at 6 {{non-constexpr declaration of 'f' follows constexpr declaration}}
+// expected-note at 5 {{previous}}
+#else
+// expected-warning at 5 {{'constexpr' non-static member function will not be implicitly 'const' in C++1y; add 'const' to avoid a change in behavior}}
+#endif

Modified: cfe/trunk/test/SemaCXX/enum-unscoped-nonexistent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-unscoped-nonexistent.cpp?rev=179969&r1=179968&r2=179969&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enum-unscoped-nonexistent.cpp (original)
+++ cfe/trunk/test/SemaCXX/enum-unscoped-nonexistent.cpp Sat Apr 20 20:08:50 2013
@@ -5,8 +5,8 @@ struct Base {
 };
 template<typename T> struct S : Base {
   enum E : int;
-  constexpr int f();
-  constexpr int g(); // expected-note {{declared here}}
+  constexpr int f() const;
+  constexpr int g() const; // expected-note {{declared here}}
   void h();
 };
 template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}}
@@ -16,13 +16,13 @@ template<typename T> enum S<T>::E : int
 
 // The unqualified-id here names a member of the non-dependent base class Base
 // and not the injected enumerator name 'a' from the specialization.
-template<typename T> constexpr int S<T>::f() { return a; }
+template<typename T> constexpr int S<T>::f() const { return a; }
 static_assert(S<char>().f() == 1, "");
 static_assert(S<int>().f() == 1, "");
 
 // The unqualified-id here names a member of the current instantiation, which
 // bizarrely might not exist in some instantiations.
-template<typename T> constexpr int S<T>::g() { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}}
+template<typename T> constexpr int S<T>::g() const { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}}
 static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} expected-note {{undefined}}
 static_assert(S<short>().g() == 2, "");
 static_assert(S<long>().g() == 8, "");





More information about the cfe-commits mailing list