summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-05-25 22:06:25 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-05-25 22:06:25 +0000
commitc0d04a2567c22631595bed8092bc042bb91ea4ee (patch)
treedc5bfa9800503e029218ee5be36c1f7a42cf4f08
parentdca7651d59907b6f62a0bcfc12781ccbc27cf810 (diff)
downloadbcm5719-llvm-c0d04a2567c22631595bed8092bc042bb91ea4ee.tar.gz
bcm5719-llvm-c0d04a2567c22631595bed8092bc042bb91ea4ee.zip
Fix rejects-valid on constexpr function that accesses a not-yet-defined 'extern
const' variable. That variable might be defined as 'constexpr', so we cannot prove that a use of it could never be a constant expression. llvm-svn: 270774
-rw-r--r--clang/lib/AST/ExprConstant.cpp11
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx11.cpp14
2 files changed, 22 insertions, 3 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9b17db6f551..6c8a650967e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2706,7 +2706,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
} else {
// FIXME: Allow folding of values of any literal type in all languages.
- if (Info.getLangOpts().CPlusPlus11) {
+ if (Info.checkingPotentialConstantExpression() &&
+ VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) {
+ // The definition of this variable could be constexpr. We can't
+ // access it right now, but may be able to in future.
+ } else if (Info.getLangOpts().CPlusPlus11) {
Info.Diag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
} else {
@@ -5456,8 +5460,9 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
}
auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
- Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0,
- std::distance(RD->field_begin(), RD->field_end()));
+ if (Result.isUninit())
+ Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0,
+ std::distance(RD->field_begin(), RD->field_end()));
unsigned ElementNo = 0;
bool Success = true;
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 47606b4f036..a755f48048a 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1181,6 +1181,20 @@ namespace ExternConstexpr {
constexpr int j = 0;
constexpr int k; // expected-error {{default initialization of an object of const type}}
}
+
+ extern const int q;
+ constexpr int g() { return q; }
+ constexpr int q = g();
+ static_assert(q == 0, "zero-initialization should precede static initialization");
+
+ extern int r; // expected-note {{here}}
+ constexpr int h() { return r; } // expected-error {{never produces a constant}} expected-note {{read of non-const}}
+
+ struct S { int n; };
+ extern const S s;
+ constexpr int x() { return s.n; }
+ constexpr S s = {x()};
+ static_assert(s.n == 0, "zero-initialization should precede static initialization");
}
namespace ComplexConstexpr {
OpenPOWER on IntegriCloud