EricWF marked 10 inline comments as done.
EricWF added inline comments.

================
Comment at: include/clang/AST/SourceLocExprScope.h:39
+    //    static_assert(foo() == __LINE__);
+    return OldVal == nullptr || isa<CXXDefaultInitExpr>(DefaultExpr) ||
+           !OldVal->isInSameContext(EvalContext);
----------------
rsmith wrote:
> Do we want the `isa` check here? I'd think the same problem would occur for 
> default initializers:
> 
> ```
> struct A {
>   int n = __builtin_LINE();
> };
> struct B {
>   A a = {};
> };
> B b = {}; // should give this context as the current one, not the context of 
> the initializer inside struct B
> ```
Good catch. Fixed.


================
Comment at: include/clang/AST/SourceLocExprScope.h:44
+public:
+  SourceLocExprScopeBase(const Expr *DefaultExpr, SourceLocExprScopeBase 
**Dest,
+                         EvalContextType *EvalContext)
----------------
rsmith wrote:
> I think it'd be cleaner to add a
> 
> ```
> struct Current {
>   SourceLocExprScopeBase *Scope;
> };
> ```
> 
> maybe with members to get the location and context for a given 
> `SourceLocExpr`, and to pass in a `SourceLocExprScopeBase::Current &` here 
> rather than a `SourceLocExprScopeBase **`.
Done. Hopefully I understood the comment.


================
Comment at: include/clang/Sema/Sema.h:4463
+
+  /// \brief build a potentially resolved SourceLocExpr.
+  ///
----------------
rsmith wrote:
> Capitalize "build" here.
Done and removed `\brief`.


================
Comment at: lib/AST/Expr.cpp:1924-1931
+  auto CreateString = [&](StringRef SVal) {
+    QualType StrTy = BuildSourceLocExprType(Ctx, getIdentType(),
+                                            /*IsArray*/ true, SVal.size() + 1);
+    StringLiteral *Lit = StringLiteral::Create(Ctx, SVal, StringLiteral::Ascii,
+                                               /*Pascal*/ false, StrTy, Loc);
+    assert(Lit && "should not be null");
+    return Lit;
----------------
rsmith wrote:
> It doesn't seem reasonable to create a new `StringLiteral` each time a 
> `SourceLocExpr` is (constant-)evaluated, and seems like it would be unsound 
> in some cases (we require that reevaluation produces the same result).
> 
> I think the `StringLiteral` here is just for convenience, right? (Instead we 
> could model the `SourceLocExpr` as being its own kind of array lvalue for the 
> purpose of constant expression evaluation, like we do for `ObjCEncodeExpr` 
> for instance.)
OK. I think I have a solution for this. Please forgive my poor explanation of 
the problem. The problem was two fold:

First, the type of `SourceLocExpr` represents the decayed type of the 
underlying array, and not the array type or value-category itself (as 
`StringLiteral` and `ObjCEncodeExpr` do). Therefore it takes additional work to 
propagate and ensure that the existing machinery uses the "real array type" of 
the `SourceLocExpr` and not the type of the `SourceLocExpr` itself.

Second,,we need to determine, store, and propagate  the type,, value category, 
and value of a `SourceLocExpr` corresponding to the context in which we first 
encounter the  `SourceLocExpr. None of this contextual information is available 
in the AST after the fact. A lazy model where `SourceLocExpr` pretends to be a 
placeholder for the "real array type and value" until said subelements are 
actually accessed will produce different results than if the `SourceLocExpr` 
was correctly evaluated in the context it was initially encountered.

For Example:
```
const char *cur_file(const char *f = __builtin_FILE()) { return f; }
struct TestInit {
#line 100 "initial_scope.cpp"
  const char *my_file = cur_file();
  TestInit() {} // FILE should point here. We need to transform/determine the 
value and type of the `SourceLocExpr` in this context.
};
#line 200 "new_scope.cpp"
// If we delay evaluating `__builtin_FILE()` until this point, where it's 
actually needed, it will return `new_scope.cpp`,
// because we've already exited the `CXXDefaultInitExpr` scope created when 
first evaluating `TestInit() = default`. 
TestInit Default;
static_assert(strcmp(Default.my_file, "initial_scope.cpp") == 0); // Fails if 
lazily evaluated!
```

I worked around this problem by storing the "real array type", the used 
location, and the used context of  the `__builtin_FOO())` expression in the 
`LValueBase` produced when we first consider the `__builtin_FOO()` expression. 


================
Comment at: lib/AST/ExprConstant.cpp:698-704
+    /// \brief Source location information about the default argument 
expression
+    /// we're evaluating, if any.
+    SourceLocExprScope *CurCXXDefaultArgScope = nullptr;
+
+    /// \brief Source location information about the default member initializer
+    /// we're evaluating, if any.
+    SourceLocExprScope *CurCXXDefaultInitScope = nullptr;
----------------
rsmith wrote:
> Do we really need both of these? It would seem like one 'current' scope would 
> be sufficient to me.
Indeed, we don't seem to need both so I've removed one.


================
Comment at: lib/CodeGen/CGExprScalar.cpp:595
+    } else {
+      StringLiteral *Str = SLE->getStringValue(Ctx, Loc, DC);
+      return CGF.EmitArrayToPointerDecay(Str).getPointer();
----------------
rsmith wrote:
> Should we make some attempt to reuse the same string literal for multiple 
> source locations denoting the same file?
I think I've addressed this. Instead of creating a `StringLiteral` expressions 
to evaluate, the new code uses `GetAddrOfConstentCString` to create the 
constant address corresponding to the string value specified by the 
`SourceLocExpr`.


https://reviews.llvm.org/D37035



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D37035: I... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D370... Eric Fiselier via Phabricator via cfe-commits
    • [PATCH] D370... Eric Fiselier via Phabricator via cfe-commits

Reply via email to