Do not crash if IsInHeader is called for builtin
In very particular circumstances (see test case), VisitFunctionDecl would see a function definition that was an implicit constructor of a builtin (va_list_tag). Rather than crashing for implicit code, just say it's not in a header. This feels a little questionable, because depending on how IsInHeader is used, it might be misleading that it returns false for builtins/implicit code. But I think it makes sense for now. Fixes issue #1162.
This commit is contained in:
parent
44fa8c7bd0
commit
cced95dba5
2
iwyu.cc
2
iwyu.cc
|
@ -1777,7 +1777,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> {
|
|||
}
|
||||
if (!IsInHeader(decl)) {
|
||||
// No point in author-intent analysis of function definitions
|
||||
// in source files.
|
||||
// in source files or for builtins.
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -174,7 +174,11 @@ bool IsInScratchSpace(SourceLocation loc) {
|
|||
|
||||
bool IsInHeader(const clang::Decl* decl) {
|
||||
const FileEntry* containing_file = GetFileEntry(decl);
|
||||
CHECK_(containing_file);
|
||||
if (!containing_file) {
|
||||
// This is a builtin, or something is terribly wrong.
|
||||
// At any rate, we're not in a header.
|
||||
return false;
|
||||
}
|
||||
return !GlobalSourceManager()->isMainFile(*containing_file);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
//===--- template_varargs.cc - test input file for iwyu -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This is a testcase heavily reduced from the most representative
|
||||
// Boost.Serialization example available online:
|
||||
// https://stackoverflow.com/a/33226687/96963.
|
||||
//
|
||||
// This input would previously crash IWYU because the implicit constructor of
|
||||
// __builtin_va_list inside the virtual member function in a template does not
|
||||
// have any location information.
|
||||
|
||||
template <class T>
|
||||
class Varargs {
|
||||
// Virtual member function is traversed as part of instantiation.
|
||||
virtual void* unused(unsigned, ...) const {
|
||||
__builtin_va_list x;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Creator {
|
||||
static T make() {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
// Necessary complications to instantiate Varargs in a deeply nested context.
|
||||
struct Base {
|
||||
Base(const Varargs<int>&);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Derived : Base {
|
||||
Derived() : Base(Creator<Varargs<int>>::make()) {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void InstantiateDerived() {
|
||||
// Only instantiate the template, don't call the method.
|
||||
(void)Creator<Derived<T>>::make;
|
||||
}
|
||||
|
||||
void p() {
|
||||
InstantiateDerived<int>();
|
||||
}
|
||||
|
||||
/**** IWYU_SUMMARY
|
||||
|
||||
(tests/cxx/template_varargs.cc has correct #includes/fwd-decls)
|
||||
|
||||
***** IWYU_SUMMARY */
|
Loading…
Reference in New Issue