<html>
<head>
<base href="https://llvm.org/bugs/" />
</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 --- - functionDecl->getLocation of specializations incorrectly points at template definition"
href="https://llvm.org/bugs/show_bug.cgi?id=30338">30338</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>functionDecl->getLocation of specializations incorrectly points at template definition
</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>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>-New Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>lukasza@chromium.org
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>This is almost, but not quite similar to
<a class="bz_bug_link
bz_status_NEW "
title="NEW --- - ParmVarDecl corresponding to unnamed parameter incorrectly has a name"
href="show_bug.cgi?id=29145">https://llvm.org/bugs/show_bug.cgi?id=29145</a>
Expected behavior:
1. The FunctionDecl corresponding to
template void foo<int>(const int& i);
should have getLocation point at line 5.
2. Iterating/matching over all FunctionDecls and generating replacements
for f>getLocation() should cover all occurrences of the function name.
Actual behavior:
1. There are 2 FunctionDecls.
Dump of one of them corresponds to line 3 of the input.
Dump of second of them corresponds to line 5 of the input, but
getLocation incorrectly says "input.cc:3"
2. Generating replacements based on FunctionDecl::getLocation() would
result in:
template <typename T>
void RenamedFoo(const T& t) {} // <- rename happens correctly here.
// No rename below, because of wrong source locations in the AST:
template void foo<int>(const int& i);
3. Output of the repro program below:
---------------------------------
parm->getName() : t
parm->getLocation() : 'input.cc:3:25'
func->getLocation() : 'input.cc:3:12'
func->dump() :
FunctionDecl 0x3a20ca0 <input.cc:3:7, col:29> col:12 foo 'void (const T
&)'
|-ParmVarDecl 0x3a20b98 <col:16, col:25> col:25 t 'const T &'
`-CompoundStmt 0x3a20de0 <col:28, col:29>
---------------------------------
parm->getName() : t
parm->getLocation() : 'input.cc:3:25'
func->getLocation() : 'input.cc:3:12'
func->dump() :
FunctionDecl 0x3a21190 <input.cc:3:7, col:29> col:12 foo 'void (const
int &)'
|-TemplateArgument type 'int'
|-ParmVarDecl 0x3a21108 <col:16, col:25> col:25 t 'const int &'
`-CompoundStmt 0x3a20de0 <col:28, col:29>
Repro:
#include <memory>
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetSelect.h"
using namespace clang::ast_matchers;
class ReproMatchCallback : public MatchFinder::MatchCallback {
public:
void run(const MatchFinder::MatchResult& result) override {
const clang::FunctionDecl* func =
result.Nodes.getNodeAs<clang::FunctionDecl>("func");
const clang::ParmVarDecl* parm =
result.Nodes.getNodeAs<clang::ParmVarDecl>("parm");
if (!func || !parm)
return;
llvm::outs() << "---------------------------------\n";
llvm::outs() << "parm->getName() : " << parm->getNameAsString() <<
"\n";
llvm::outs() << "parm->getLocation() : '"
<< parm->getLocation().printToString(
result.Context->getSourceManager())
<< "'\n";
llvm::outs() << "func->getLocation() : '"
<< func->getLocation().printToString(
result.Context->getSourceManager())
<< "'\n";
llvm::outs() << "func->dump() :\n";
func->dump();
}
};
int main(int argc, const char* argv[]) {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmParser();
llvm::cl::OptionCategory category("Repro.");
clang::tooling::CommonOptionsParser options(argc, argv, category);
clang::tooling::ClangTool tool(options.getCompilations(),
options.getSourcePathList());
const char* code = R"code( // line 1
template <typename T> // line 2
void foo(const T& t) {} // line 3
// line 4
template void foo<int>(const int& i); // line 5
)code";
auto matcher =
id("func", functionDecl(hasAnyParameter(id("parm", parmVarDecl()))));
MatchFinder match_finder;
ReproMatchCallback match_callback;
match_finder.addMatcher(matcher, &match_callback);
std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
clang::tooling::newFrontendActionFactory(&match_finder);
clang::tooling::runToolOnCode(factory->create(), code);
return 0;
}</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>