]> granicus.if.org Git - clang/commitdiff
Move TLS check from LValueExprEvaluator::VisitVarDecl to
authorHans Wennborg <hans@hanshq.net>
Wed, 29 Aug 2012 18:27:29 +0000 (18:27 +0000)
committerHans Wennborg <hans@hanshq.net>
Wed, 29 Aug 2012 18:27:29 +0000 (18:27 +0000)
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
test/SemaCXX/constant-expression-cxx11.cpp

index ac21b469411116ae048902ca69ed428b977242a1..fb0c4d26ea85ea9f0f8889ffb1c8cc63c8ab09e1 100644 (file)
@@ -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<const ValueDecl*>()) {
+    if (const VarDecl *Var = dyn_cast<const VarDecl>(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<ParmVarDecl>(VD)) {
       Result.set(VD, Info.CurrentCall->Index);
index 984ee1b08b606ea99d8afe9c46f9ce735cd82217..930e70d4f36f26a3f8a9bd6dbda7c58f270b53db 100644 (file)
@@ -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();
 }