<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - With __PRETTY_FUNCTION__, dereferencing same pointer produces different results at compile time vs. runtime"
href="https://bugs.llvm.org/show_bug.cgi?id=40313">40313</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>With __PRETTY_FUNCTION__, dereferencing same pointer produces different results at compile time vs. runtime
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>C++
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>comexk@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, dgregor@apple.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>The below example outputs:
string:'top level' first_eight:'Ret get_'
which indicates that "str" is equal to "Ret get_foo()" when dereferenced at
compile time, but equal to "top level" when dereferenced at runtime.
The bug seems to be in the methods ConstantLValueEmitter::VisitPredefinedExpr
and CodeGenFunction::EmitPredefinedLValue. The code seems to assume that the
current CodeGenFunction corresponds to the function the PredefinedExpr is
originally from, which is no longer guaranteed when constexpr is used.
ConstantLValueEmitter::VisitPredefinedExpr checks whether there is a current
CodeGenFunction, and calls CodeGenFunction::EmitPredefinedLValue if so. In the
below example, the constexpr variable is instantiated at a global level, so
there is no current CodeGenFunction. In this case,
ConstantLValueEmitter::VisitPredefinedExpr hardcodes "top level" as the string
literal. This is strange, since the string literal was computed earlier on and
is included in the PredefinedExpr object as the return value of
getFunctionName().
If the constexpr variable declaration is moved to within a function, it appears
to return the right string but, as far as I can tell, is subtly incorrect.
CodeGenFunction::EmitPredefinedLValue normally calls getFunctionName() for the
contents of the string literal, but uses the current CodeGenFunction, combined
with the type of predefined expr, to name the *symbol* containing that literal.
This name is supposed to uniquely identify the string contents, which it does
if the current CodeGenFunction is the function the PredefinedExpr was from
(whose name was used to compute the string contents), but not if it's some
random other function.
#include <stdio.h>
#include <string.h>
struct Ret {
const char *string;
char first_eight[8];
char zero;
};
constexpr Ret get_foo() {
constexpr const char *str = __PRETTY_FUNCTION__;
return {
str,
{str[0], str[1], str[2], str[3],
str[4], str[5], str[6], str[7]},
'\0'
};
}
constexpr Ret foo = get_foo();
int main() {
printf("string:'%s' first_eight:'%s'\n", foo.string, foo.first_eight);
}</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>