[cfe-commits] r147031 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp test/SemaCXX/constant-expression-cxx11.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Tue Dec 20 18:55:13 PST 2011
Author: rsmith
Date: Tue Dec 20 20:55:12 2011
New Revision: 147031
URL: http://llvm.org/viewvc/llvm-project?rev=147031&view=rev
Log:
C++11 half of r147023: In C++11, additionally eagerly instantiate:
- constexpr function template instantiations
- variables of reference type
- constexpr variables
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=147031&r1=147030&r2=147031&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Dec 20 20:55:12 2011
@@ -1025,6 +1025,12 @@
/// \endcode
bool extendsLifetimeOfTemporary() const;
+ /// \brief Determine whether this variable's value can be used in a
+ /// constant expression, according to the relevant language standard.
+ /// This only checks properties of the declaration, and does not check
+ /// whether the initializer is in fact a constant expression.
+ bool isUsableInConstantExpressions() const;
+
EvaluatedStmt *ensureEvaluatedStmt() const;
/// \brief Attempt to evaluate the value of the initializer attached to this
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=147031&r1=147030&r2=147031&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Dec 20 20:55:12 2011
@@ -1339,6 +1339,26 @@
Init = I;
}
+bool VarDecl::isUsableInConstantExpressions() const {
+ const LangOptions &Lang = getASTContext().getLangOptions();
+
+ // Only const variables can be used in constant expressions in C++. C++98 does
+ // not require the variable to be non-volatile, but we consider this to be a
+ // defect.
+ if (!Lang.CPlusPlus ||
+ !getType().isConstQualified() || getType().isVolatileQualified())
+ return false;
+
+ // In C++, const, non-volatile variables of integral or enumeration types
+ // can be used in constant expressions.
+ if (getType()->isIntegralOrEnumerationType())
+ return true;
+
+ // Additionally, in C++11, non-volatile constexpr variables and references can
+ // be used in constant expressions.
+ return Lang.CPlusPlus0x && (isConstexpr() || getType()->isReferenceType());
+}
+
/// Convert the initializer for this declaration to the elaborated EvaluatedStmt
/// form, which contains extra information on the evaluated value of the
/// initializer.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=147031&r1=147030&r2=147031&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 20 20:55:12 2011
@@ -6544,8 +6544,7 @@
for (unsigned I = 0, N = Notes.size(); I != N; ++I)
Diag(Notes[I].first, Notes[I].second);
}
- } else if (getLangOptions().CPlusPlus && !Type.isVolatileQualified() &&
- Type.isConstQualified() && Type->isIntegralOrEnumerationType()) {
+ } else if (var->isUsableInConstantExpressions()) {
// Check whether the initializer of a const variable of integral or
// enumeration type is an ICE now, since we can't tell whether it was
// initialized by a constant expression if we check later.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=147031&r1=147030&r2=147031&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Dec 20 20:55:12 2011
@@ -9491,6 +9491,11 @@
cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
Loc));
+ else if (Function->getTemplateInstantiationPattern()->isConstexpr())
+ // Do not defer instantiations of constexpr functions, to avoid the
+ // expression evaluator needing to call back into Sema if it sees a
+ // call to such a function.
+ InstantiateFunctionDefinition(Loc, Function);
else
PendingInstantiations.push_back(std::make_pair(Function, Loc));
}
@@ -9526,9 +9531,9 @@
// This is a modification of an existing AST node. Notify listeners.
if (ASTMutationListener *L = getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
- QualType T = Var->getType();
- if (T.isConstQualified() && !T.isVolatileQualified() &&
- T->isIntegralOrEnumerationType())
+ if (Var->isUsableInConstantExpressions())
+ // Do not defer instantiations of variables which could be used in a
+ // constant expression.
InstantiateStaticDataMemberDefinition(Loc, Var);
else
PendingInstantiations.push_back(std::make_pair(Var, Loc));
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=147031&r1=147030&r2=147031&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 Tue Dec 20 20:55:12 2011
@@ -68,7 +68,7 @@
};
// template stuff
-template <typename T> constexpr T ft(T t) { return t; } // unexpected-note {{here}}
+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();
@@ -89,8 +89,7 @@
template <> char S::g() { return 0; } // expected-error {{no function template matches}}
template <> double S::g() const { return 0; } // ok
-// FIXME: The initializer is a constant expression.
-constexpr int i3 = ft(1); // unexpected-error {{must be initialized by a constant expression}} unexpected-note {{undefined function 'ft<int>'}}
+constexpr int i3 = ft(1);
void test() {
// ignore constexpr when instantiating with non-literal
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=147031&r1=147030&r2=147031&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue Dec 20 20:55:12 2011
@@ -8,16 +8,17 @@
}
-template<typename T> constexpr T id(const T &t) { return t; } // expected-note {{here}}
-// FIXME: support templates here.
-//template<typename T> constexpr T min(const T &a, const T &b) {
-// return a < b ? a : b;
-//}
-//template<typename T> constexpr T max(const T &a, const T &b) {
-// return a < b ? b : a;
-//}
-constexpr int min(const int &a, const int &b) { return a < b ? a : b; }
-constexpr int max(const int &a, const int &b) { return a < b ? b : a; }
+typedef decltype(sizeof(char)) size_t;
+
+template<typename T> constexpr T id(const T &t) { return t; }
+template<typename T> constexpr T min(const T &a, const T &b) {
+ return a < b ? a : b;
+}
+template<typename T> constexpr T max(const T &a, const T &b) {
+ return a < b ? b : a;
+}
+template<typename T, size_t N> constexpr T *begin(T (&xs)[N]) { return xs; }
+template<typename T, size_t N> constexpr T *end(T (&xs)[N]) { return xs + N; }
struct MemberZero {
constexpr int zero() { return 0; }
@@ -84,8 +85,7 @@
template<int n> struct IntParam {};
using IntParam0 = IntParam<0>;
- // FIXME: This should be accepted once we implement the new ICE rules.
- using IntParam0 = IntParam<id(0)>; // expected-error {{not an integral constant expression}}
+ using IntParam0 = IntParam<id(0)>;
using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} expected-error {{not an integral constant expression}}
}
@@ -94,8 +94,7 @@
switch (n) {
// FIXME: Produce the 'add ()' fixit for this.
case MemberZero().zero: // desired-error {{did you mean to call it with no arguments?}} expected-error {{not an integer constant expression}} expected-note {{non-literal type '<bound member function type>'}}
- // FIXME: This should be accepted once we implement the new ICE rules.
- case id(1): // expected-error {{not an integer constant expression}} expected-note {{undefined function}}
+ case id(1):
return;
}
}
@@ -352,14 +351,8 @@
namespace StringLiteral {
-// FIXME: Refactor this once we support constexpr templates.
-constexpr int MangleChars(const char *p) {
- return *p + 3 * (*p ? MangleChars(p+1) : 0);
-}
-constexpr int MangleChars(const char16_t *p) {
- return *p + 3 * (*p ? MangleChars(p+1) : 0);
-}
-constexpr int MangleChars(const char32_t *p) {
+template<typename Char>
+constexpr int MangleChars(const Char *p) {
return *p + 3 * (*p ? MangleChars(p+1) : 0);
}
@@ -383,9 +376,6 @@
return (a+1 >= b) ? a : max_iter(a, max_element(a+1, b));
}
-constexpr const char *begin(const char (&arr)[45]) { return arr; }
-constexpr const char *end(const char (&arr)[45]) { return arr + 45; }
-
constexpr char str[] = "the quick brown fox jumped over the lazy dog";
constexpr const char *max = max_element(begin(str), end(str));
static_assert(*max == 'z', "");
@@ -400,12 +390,10 @@
namespace Array {
-// FIXME: Use templates for these once we support constexpr templates.
-constexpr int Sum(const int *begin, const int *end) {
+template<typename Iter>
+constexpr auto Sum(Iter begin, Iter end) -> decltype(+*begin) {
return begin == end ? 0 : *begin + Sum(begin+1, end);
}
-constexpr const int *begin(const int (&xs)[5]) { return xs; }
-constexpr const int *end(const int (&xs)[5]) { return xs + 5; }
constexpr int xs[] = { 1, 2, 3, 4, 5 };
constexpr int ys[] = { 5, 4, 3, 2, 1 };
More information about the cfe-commits
mailing list