From 48def65d1cfbd020c5d4a7e542a00d63808c6060 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 29 Aug 2012 18:27:29 +0000 Subject: [PATCH] Move TLS check from LValueExprEvaluator::VisitVarDecl to CheckLValueConstantExpression. Richard pointed out that using the address of a TLS variable is ok in a core C++11 constant expression, as long as it isn't part of the eventual result of constant expression evaluation. Having the check in CheckLValueConstantExpression accomplishes this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162850 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 10 ++++++++-- test/SemaCXX/constant-expression-cxx11.cpp | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index ac21b46941..fb0c4d26ea 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -987,6 +987,14 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, LVal.getLValueCallIndex() == 0) && "have call index for global lvalue"); + // Check if this is a thread-local variable. + if (const ValueDecl *VD = Base.dyn_cast()) { + if (const VarDecl *Var = dyn_cast(VD)) { + if (Var->isThreadSpecified()) + return false; + } + } + // Allow address constant expressions to be past-the-end pointers. This is // an extension: the standard requires them to point to an object. if (!IsReferenceType) @@ -2832,8 +2840,6 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { } bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { - if (VD->isThreadSpecified()) - return Error(E); if (!VD->getType()->isReferenceType()) { if (isa(VD)) { Result.set(VD, Info.CurrentCall->Index); diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 984ee1b08b..930e70d4f3 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1377,7 +1377,16 @@ namespace ConditionalLValToRVal { namespace TLS { __thread int n; - constexpr int &f() { // expected-error {{constexpr function never produces a constant expression}} - return n; // expected-note {{subexpression not valid in a constant expression}} - } + int m; + + constexpr bool b = &n == &n; + + constexpr int *p = &n; // expected-error{{constexpr variable 'p' must be initialized by a constant expression}} + + constexpr int *f() { return &n; } + constexpr int *q = f(); // expected-error{{constexpr variable 'q' must be initialized by a constant expression}} + constexpr bool c = f() == f(); + + constexpr int *g() { return &m; } + constexpr int *r = g(); }