1 //===--- HeaderAnalysis.cpp -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Tooling/Inclusions/HeaderAnalysis.h" 10 #include "clang/Basic/SourceLocation.h" 11 #include "clang/Lex/HeaderSearch.h" 12 13 namespace clang::tooling { 14 namespace { 15 16 // Is Line an #if or #ifdef directive? 17 // FIXME: This makes headers with #ifdef LINUX/WINDOWS/MACOS marked as non 18 // self-contained and is probably not what we want. 19 bool isIf(llvm::StringRef Line) { 20 Line = Line.ltrim(); 21 if (!Line.consume_front("#")) 22 return false; 23 Line = Line.ltrim(); 24 return Line.startswith("if"); 25 } 26 27 // Is Line an #error directive mentioning includes? 28 bool isErrorAboutInclude(llvm::StringRef Line) { 29 Line = Line.ltrim(); 30 if (!Line.consume_front("#")) 31 return false; 32 Line = Line.ltrim(); 33 if (!Line.startswith("error")) 34 return false; 35 return Line.contains_insensitive( 36 "includ"); // Matches "include" or "including". 37 } 38 39 // Heuristically headers that only want to be included via an umbrella. 40 bool isDontIncludeMeHeader(llvm::MemoryBufferRef Buffer) { 41 StringRef Content = Buffer.getBuffer(); 42 llvm::StringRef Line; 43 // Only sniff up to 100 lines or 10KB. 44 Content = Content.take_front(100 * 100); 45 for (unsigned I = 0; I < 100 && !Content.empty(); ++I) { 46 std::tie(Line, Content) = Content.split('\n'); 47 if (isIf(Line) && isErrorAboutInclude(Content.split('\n').first)) 48 return true; 49 } 50 return false; 51 } 52 53 } // namespace 54 55 bool isSelfContainedHeader(const FileEntry *FE, const SourceManager &SM, 56 HeaderSearch &HeaderInfo) { 57 assert(FE); 58 if (!HeaderInfo.isFileMultipleIncludeGuarded(FE) && 59 !HeaderInfo.hasFileBeenImported(FE)) 60 return false; 61 // This pattern indicates that a header can't be used without 62 // particular preprocessor state, usually set up by another header. 63 return !isDontIncludeMeHeader( 64 const_cast<SourceManager &>(SM).getMemoryBufferForFileOrNone(FE).value_or( 65 llvm::MemoryBufferRef())); 66 } 67 } // namespace clang::tooling 68