private: bool removeInline(FunctionDecl const * decl, SourceLocation * inlineLoc) {
assert(inlineLoc != nullptr);
assert(inlineLoc->isInvalid()); unsigned n = {}; // avoid -Werror=maybe-uninitialized auto end = Lexer::getLocForEndOfToken(
compiler.getSourceManager().getExpansionLoc(decl->getEndLoc()), 0,
compiler.getSourceManager(), compiler.getLangOpts());
assert(end.isValid()); for (auto loc = compiler.getSourceManager().getExpansionLoc(
decl->getBeginLoc());
loc != end; loc = loc.getLocWithOffset(std::max<unsigned>(n, 1)))
{
n = Lexer::MeasureTokenLength(
loc, compiler.getSourceManager(), compiler.getLangOpts());
StringRef s(compiler.getSourceManager().getCharacterData(loc), n); //TODO: see compilerplugins/clang/override.cxx: if (compat::starts_with(s, "\\\n")) {
s = s.drop_front(2);
} if (s == "inline") { if (!compiler.getSourceManager().isMacroArgExpansion(loc)) {
*inlineLoc = loc;
} break;
} elseif (s == "#") { // Hard to pick the right 'inline' in code like // // #if 1 // static // #else // inline // #endif // inline void f() {} // // so just give up once a preprocessing directive is seen: break;
}
} if (rewriter != nullptr && inlineLoc->isValid()) { for (auto loc = inlineLoc->getLocWithOffset(
std::max<unsigned>(n, 1));;)
{
assert(loc != end); unsigned n2 = Lexer::MeasureTokenLength(
loc, compiler.getSourceManager(), compiler.getLangOpts());
StringRef s(
compiler.getSourceManager().getCharacterData(loc), n2); //TODO: see compilerplugins/clang/override.cxx: if (compat::starts_with(s, "\\\n")) {
s = s.drop_front(2);
} if (!s.empty()) { break;
}
n2 = std::max<unsigned>(n2, 1);
n += n2;
loc = loc.getLocWithOffset(n2);
} if (removeText(*inlineLoc, n, RewriteOptions(RemoveLineIfEmpty))) { returntrue;
}
} returnfalse;
}
SourceLocation unwindTo(SourceLocation const & loc, StringRef name) { if (!loc.isMacroID()) { return SourceLocation();
} auto l = compiler.getSourceManager().getImmediateMacroCallerLoc(loc); return
(Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts())
== name)
? l : unwindTo(l, name);
}
bool isInMacroExpansion(FunctionDecl const * decl, StringRef name) { auto loc = unwindTo(decl->getBeginLoc(), name); return loc.isValid() && loc == unwindTo(decl->getEndLoc(), name);
}
bool handleNonExternalLinkage(FunctionDecl const * decl) { if (decl->getLinkageInternal() >= compat::Linkage::Module) { returnfalse;
} if (!compiler.getSourceManager().isInMainFile(decl->getLocation())) { // There *may* be benefit to "static inline" in include files (esp. in C code, where an // inline function with external linkage still requires an external definition), so // just ignore those for now: returntrue;
} if (isInMacroExpansion(decl, "G_DEFINE_TYPE")
|| isInMacroExpansion(decl, "G_DEFINE_TYPE_WITH_CODE")
|| isInMacroExpansion(decl, "G_DEFINE_TYPE_WITH_PRIVATE"))
{ returntrue;
}
SourceLocation inlineLoc; if (!removeInline(decl, &inlineLoc)) {
report(
DiagnosticsEngine::Warning, "function has no external linkage but is explicitly declared 'inline'",
inlineLoc.isValid() ? inlineLoc : decl->getBeginLoc())
<< decl->getSourceRange();
} returntrue;
}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.