aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-01-12 06:08:57 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-01-12 06:08:57 +0000
commit61e616206413d1779c7545c7a8ad1ce1129ad9c1 (patch)
tree864235e3a0798289f3c267470fde05b3c0f171a0
parent746f5bcbfde5b25269169c63c66492311673b67d (diff)
Allow constant-folding of references which were formed in a manner not permitted
in a constant expression, for compatibility with g++. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148020 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ExprConstant.cpp16
-rw-r--r--test/CXX/expr/expr.const/p2-0x.cpp3
-rw-r--r--test/CodeGenCXX/const-init.cpp7
-rw-r--r--www/cxx_status.html6
4 files changed, 18 insertions, 14 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 36addddcc5..9df53cd5bf 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -832,7 +832,8 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
/// Check that this reference or pointer core constant expression is a valid
/// value for an address or reference constant expression. Type T should be
-/// either LValue or CCValue.
+/// either LValue or CCValue. Return true if we can fold this expression,
+/// whether or not it's a constant expression.
template<typename T>
static bool CheckLValueConstantExpression(EvalInfo &Info, const Expr *E,
const T &LVal, APValue &Value,
@@ -854,19 +855,15 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, const Expr *E,
} else {
Info.Diag(E->getExprLoc());
}
+ // Don't allow references to temporaries to escape.
return false;
}
bool IsReferenceType = E->isGLValue();
if (Designator.Invalid) {
- // This is not a core constant expression. A diagnostic will have already
- // been produced.
- if (IsReferenceType)
- return false;
-
- // Allow this for pointers, so we can fold things like integers cast to
- // pointers.
+ // This is not a core constant expression. An appropriate diagnostic will
+ // have already been produced.
Value = APValue(LVal.getLValueBase(), LVal.getLValueOffset(),
APValue::NoLValuePath());
return true;
@@ -884,7 +881,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, const Expr *E,
if (!Base) {
// FIXME: diagnostic
Info.CCEDiag(E->getExprLoc());
- return false;
+ return true;
}
// Does this refer one past the end of some object?
@@ -897,7 +894,6 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, const Expr *E,
else
Info.Note(Base.dyn_cast<const Expr*>()->getExprLoc(),
diag::note_constexpr_temporary_here);
- return false;
}
return true;
diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp
index 78d78b64c7..cece22d9b2 100644
--- a/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/test/CXX/expr/expr.const/p2-0x.cpp
@@ -134,8 +134,9 @@ namespace UndefinedBehavior {
constexpr const int &f(const int *q) {
return q[0]; // expected-note {{dereferenced pointer past the end of subobject of 's' is not a constant expression}}
}
+ constexpr int n = (f(p), 0); // expected-error {{constant expression}} expected-note {{in call to 'f(&s.m + 1)'}}
struct T {
- int n : f(p); // expected-error {{not an integer constant expression}} expected-note {{in call to 'f(&s.m + 1)'}}
+ int n : f(p); // expected-error {{not an integer constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
};
namespace Ptr {
diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp
index 1cfcdba22f..201ce8f0c6 100644
--- a/test/CodeGenCXX/const-init.cpp
+++ b/test/CodeGenCXX/const-init.cpp
@@ -69,3 +69,10 @@ void UnfoldableAddrLabelDiff() { static __int128_t x = (long)&&a-(long)&&b; a:b:
// But make sure we do fold this.
// CHECK: @_ZZ21FoldableAddrLabelDiffvE1x = internal global i64 sub (i64 ptrtoint (i8* blockaddress(@_Z21FoldableAddrLabelDiffv
void FoldableAddrLabelDiff() { static long x = (long)&&a-(long)&&b; a:b:return;}
+
+// CHECK: @i = constant i32* bitcast (float* @PR9558 to i32*)
+int &i = reinterpret_cast<int&>(PR9558);
+
+int arr[2];
+// CHECK: @pastEnd = constant i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @arr to i8*), i64 8) to i32*)
+int &pastEnd = arr[2];
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 0dc1b86712..742d54e3ff 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -8,7 +8,7 @@
<link type="text/css" rel="stylesheet" href="content.css">
<style type="text/css">
.none { background-color: #FFCCCC }
- .partial { background-color: #FFFF99 }
+ .svn { background-color: #FFFF99 }
.full { background-color: #CCFF99 }
th { background-color: #FFDDAA }
</style>
@@ -156,7 +156,7 @@ with clang; other versions have not been tested.</p>
<td>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf">N2764
</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Generalized attributes</td>
@@ -238,7 +238,7 @@ with clang; other versions have not been tested.</p>
<tr>
<td>Extending <code>sizeof</code></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html">N2253</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Inline namespaces</td>