diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-05-25 22:06:25 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-05-25 22:06:25 +0000 |
commit | c0d04a2567c22631595bed8092bc042bb91ea4ee (patch) | |
tree | dc5bfa9800503e029218ee5be36c1f7a42cf4f08 | |
parent | dca7651d59907b6f62a0bcfc12781ccbc27cf810 (diff) | |
download | bcm5719-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.cpp | 11 | ||||
-rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx11.cpp | 14 |
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 { |