Skip to content

[clang][Sema] Suggest/Hint Standard Library Include File #146227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Mr-Anyone
Copy link
Contributor

Clang now tries to suggest and hint standard library include file by emitting the following.

    4 |     std::unordered_map<std::string, std::string> map;
      |          ^~~~~~~~~~~~~
main.cpp:4:10: note: maybe try to include <unordered_map>; 'std::unordered_map' is defined in <unordered_map>
main.cpp:4:10: note: 'std::unordered_map' is a c++11 feature
main.cpp:4:42: note: maybe try to include <string>; 'std::string' is defined in <string>

This works for both C and C++.

fixes #120388

Clang now tries to suggest and hint standard library include file by emitting
the following.

```
    4 |     std::unordered_map<std::string, std::string> map;
      |          ^~~~~~~~~~~~~
main.cpp:4:10: note: maybe try to include <unordered_map>; 'std::unordered_map' is defined in <unordered_map>
main.cpp:4:10: note: 'std::unordered_map' is a c++11 feature
main.cpp:4:42: note: maybe try to include <string>; 'std::string' is defined in <string>
```

This works for both C and C++.

fixes llvm#120388
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Jun 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 28, 2025

@llvm/pr-subscribers-clang

Author: Vincent (Mr-Anyone)

Changes

Clang now tries to suggest and hint standard library include file by emitting the following.

    4 |     std::unordered_map&lt;std::string, std::string&gt; map;
      |          ^~~~~~~~~~~~~
main.cpp:4:10: note: maybe try to include &lt;unordered_map&gt;; 'std::unordered_map' is defined in &lt;unordered_map&gt;
main.cpp:4:10: note: 'std::unordered_map' is a c++11 feature
main.cpp:4:42: note: maybe try to include &lt;string&gt;; 'std::string' is defined in &lt;string&gt;

This works for both C and C++.

fixes #120388


Patch is 644.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146227.diff

26 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4)
  • (modified) clang/include/clang/Sema/Sema.h (+10)
  • (modified) clang/include/clang/Tooling/Inclusions/StandardLibrary.h (+22)
  • (modified) clang/lib/Parse/ParseExprCXX.cpp (+14)
  • (modified) clang/lib/Sema/CMakeLists.txt (+1)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+49)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+6)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc (+429-697)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp (+55-5)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc (-5)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc (+2014-2140)
  • (modified) clang/test/Headers/stddef.c (+40-6)
  • (modified) clang/test/Headers/stddefneeds.c (+67-13)
  • (modified) clang/test/Headers/stddefneeds.cpp (+10-10)
  • (modified) clang/test/Modules/implicit-declared-allocation-functions.cppm (+12-6)
  • (modified) clang/test/Modules/macro-reexport.cpp (+3-3)
  • (modified) clang/test/Modules/stddef.cpp (+2-2)
  • (modified) clang/test/Sema/MicrosoftCompatibility.c (+1-1)
  • (modified) clang/test/Sema/builtin-setjmp.c (+5-3)
  • (modified) clang/test/Sema/c23-delayed-typo-correction-crashes.c (+2-1)
  • (modified) clang/test/Sema/implicit-builtin-decl.c (+2-1)
  • (added) clang/test/Sema/include-suggestion.c (+5)
  • (modified) clang/test/SemaCXX/constructor-initializer.cpp (+1-1)
  • (added) clang/test/SemaCXX/include-suggestions-cxx.cpp (+2458)
  • (modified) clang/test/SemaCXX/no-implicit-builtin-decls.cpp (+1-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 96477ef6ddc9a..b38dafb06e3ca 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -470,6 +470,7 @@ Improvements to Clang's diagnostics
   diagnostics. This fixes a bunch of `bool` being printed as `_Bool`, and also
   a bunch of HLSL types being printed as their C++ equivalents.
 - Clang now consistently quotes expressions in diagnostics.
+- Clang now suggest standard library include path and its associated C++ or C language version.
 - When printing types for diagnostics, clang now doesn't suppress the scopes of
   template arguments contained within nested names.
 - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f2f2152b8bbbe..96f444544291d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5978,6 +5978,10 @@ def err_template_expansion_into_fixed_list : Error<
   "template|concept}0">;
 def note_parameter_type : Note<
   "parameter of type %0 is declared here">;
+def note_standard_lib_include_suggestion : Note<
+  "maybe try to include %0; '%1' is defined in %0">;
+def note_standard_lib_version : Note<
+  "'%0' is a %1 feature">;
 
 // C++11 Variadic Templates
 def err_template_param_pack_default_arg : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9397546c8fc5d..f4c22cc255876 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3611,6 +3611,16 @@ class Sema final : public SemaBase {
                                ParsedType &SuggestedType,
                                bool IsTemplateName = false);
 
+  // Try to suggest the missing standard library include files
+  //
+  // \param SymbolName the symbol name like 'cout'
+  // \param SourceLocation the location of the note being emitted
+  // \param Namespace the namespace that must end with ::, so like 'std::'
+  void NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                            StringRef Namespace);
+  void NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                            const CXXScopeSpec *SS);
+
   /// Attempt to behave like MSVC in situations where lookup of an unqualified
   /// type name has failed in a dependent context. In these situations, we
   /// automatically form a DependentTypeName that will retry lookup in a related
diff --git a/clang/include/clang/Tooling/Inclusions/StandardLibrary.h b/clang/include/clang/Tooling/Inclusions/StandardLibrary.h
index 147f505ade058..42bbb5b3f0d8c 100644
--- a/clang/include/clang/Tooling/Inclusions/StandardLibrary.h
+++ b/clang/include/clang/Tooling/Inclusions/StandardLibrary.h
@@ -29,6 +29,27 @@ class NamespaceDecl;
 class DeclContext;
 namespace tooling {
 namespace stdlib {
+enum Version {
+  Unknown,
+
+  // c++ versions
+  CPlusPlusStart,
+  CPlusPlus11,
+  CPlusPlus14,
+  CPlusPlus17,
+  CPlusPlus20,
+  CPlusPlus23,
+  CPlusPlus26,
+  CPlusPlusEnd,
+
+  // c version
+  CStart,
+  C99,
+  C11,
+  CEnd
+};
+
+llvm::StringRef GetAsString(Version Ver);
 
 class Symbol;
 enum class Lang { C = 0, CXX, LastValue = CXX };
@@ -85,6 +106,7 @@ class Symbol {
   std::optional<Header> header() const;
   // Some symbols may be provided by multiple headers.
   llvm::SmallVector<Header> headers() const;
+  Version version() const;
 
 private:
   Symbol(unsigned ID, Lang Language) : ID(ID), Language(Language) {}
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 1ea0cf52933f6..9de0e9ca74c6f 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -226,6 +226,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
     HasScopeSpecifier = true;
   }
 
+  // If `FailedNestedNameBuilding` is true, attempt to suggest the standard
+  // include file corresponding to the current `FullNamespace` and symbol.
+  std::string FullNamespace = "";
+  bool FailedNesatedNameBuilding = false;
+
   // Preferred type might change when parsing qualifiers, we need the original.
   auto SavedType = PreferredType;
   while (true) {
@@ -454,6 +459,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
       // We have an identifier followed by a '::'. Lookup this name
       // as the name in a nested-name-specifier.
       Token Identifier = Tok;
+      FullNamespace += Identifier.getIdentifierInfo()->getName();
+      FullNamespace += "::";
+
       SourceLocation IdLoc = ConsumeToken();
       assert(Tok.isOneOf(tok::coloncolon, tok::colon) &&
              "NextToken() not working properly!");
@@ -465,6 +473,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
       if (Actions.ActOnCXXNestedNameSpecifier(
               getCurScope(), IdInfo, EnteringContext, SS, CorrectionFlagPtr,
               OnlyNamespace)) {
+        FailedNesatedNameBuilding = true;
         // Identifier is not recognized as a nested name, but we can have
         // mistyped '::' instead of ':'.
         if (CorrectionFlagPtr && IsCorrectedToColon) {
@@ -554,6 +563,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
     break;
   }
 
+  if (FailedNesatedNameBuilding && Tok.getKind() == tok::identifier) {
+    Actions.NoteStandardIncludes(Tok.getIdentifierInfo()->getName(),
+                                 Tok.getLocation(), FullNamespace);
+  }
+
   // Even if we didn't see any pieces of a nested-name-specifier, we
   // still check whether there is a tilde in this position, which
   // indicates a potential pseudo-destructor.
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 51e0ee10b080b..ff4f583bdd9bf 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -115,4 +115,5 @@ add_clang_library(clangSema
   clangEdit
   clangLex
   clangSupport
+  clangToolingInclusionsStdlib
   )
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e1cccf068b5aa..7d659a6d06f93 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -58,10 +58,12 @@
 #include "clang/Sema/SemaSwift.h"
 #include "clang/Sema/SemaWasm.h"
 #include "clang/Sema/Template.h"
+#include "clang/Tooling/Inclusions/StandardLibrary.h"
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/TargetParser/Triple.h"
@@ -805,6 +807,52 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
     assert(SS && SS->isInvalid() &&
            "Invalid scope specifier has already been diagnosed");
   }
+
+  // don't note standard include files for OpenCL and Objective C
+  if ((getLangOpts().CPlusPlus || getLangOpts().C99) && !getLangOpts().OpenCL &&
+      !getLangOpts().ObjC)
+    NoteStandardIncludes(II->getName(), IILoc, SS);
+}
+
+void Sema::NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                                StringRef Namespace) {
+  using clang::tooling::stdlib::Lang;
+
+  llvm::StringRef HeaderName = "";
+  tooling::stdlib::Lang LangOption = tooling::stdlib::Lang::C;
+  if (getLangOpts().CPlusPlus)
+    LangOption = clang::tooling::stdlib::Lang::CXX;
+
+  if (auto StdSym =
+          tooling::stdlib::Symbol::named(Namespace, SymbolName, LangOption)) {
+    if (auto Header = StdSym->header()) {
+      HeaderName = Header->name();
+      Diag(IILoc, diag::note_standard_lib_include_suggestion)
+          << HeaderName << (Namespace + SymbolName).str();
+
+      // Noting the C/C++ version as well
+      if (StdSym->version() != tooling::stdlib::Unknown) {
+        llvm::StringRef CPlusPlusVersion =
+            tooling::stdlib::GetAsString(StdSym->version());
+
+        Diag(IILoc, diag::note_standard_lib_version)
+            << (Namespace + SymbolName).str() << CPlusPlusVersion;
+      }
+    }
+  }
+}
+
+void Sema::NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                                const CXXScopeSpec *SS) {
+  std::string Namespace = "";
+  if (SS) {
+    llvm::raw_string_ostream Stream(Namespace);
+    if (SS->isValid())
+      SS->getScopeRep()->dump(Stream);
+    Stream.flush();
+  }
+
+  NoteStandardIncludes(SymbolName, IILoc, Namespace);
 }
 
 /// Determine whether the given result set contains either a type name
@@ -16784,6 +16832,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
   }
 
   Diag(Loc, diag_id) << &II;
+  NoteStandardIncludes(II.getName(), Loc, "");
   if (Corrected) {
     // If the correction is going to suggest an implicitly defined function,
     // skip the correction as not being a particularly good idea.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fc2819458a4ff..9015b70deb5d1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2660,11 +2660,17 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
   if (!SS.isEmpty()) {
     Diag(R.getNameLoc(), diag::err_no_member)
         << Name << computeDeclContext(SS, false) << NameRange;
+    NoteStandardIncludes(Name.getAsString(), R.getNameLoc(), &SS);
     return true;
   }
 
   // Give up, we can't recover.
   Diag(R.getNameLoc(), diagnostic) << Name << NameRange;
+
+  // don't note standard include files for OpenCL and Objective C
+  if ((getLangOpts().CPlusPlus || getLangOpts().C99) && !getLangOpts().OpenCL &&
+      !getLangOpts().ObjC)
+    NoteStandardIncludes(Name.getAsString(), R.getNameLoc(), /*Namespace=*/"");
   return true;
 }
 
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
index 463ce921f0672..b3a1921f3c74b 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
@@ -6,246 +6,44 @@
 // This file was generated automatically by
 // clang/tools/include-mapping/gen_std.py, DO NOT EDIT!
 //
-// Generated from cppreference offline HTML book (modified on 2018-10-28).
+// Generated from cppreference offline HTML book (modified on 2025-02-10).
 //===----------------------------------------------------------------------===//
 
-SYMBOL(ATOMIC_BOOL_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_CHAR16_T_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_CHAR32_T_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_CHAR_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_FLAG_INIT, None, <stdatomic.h>)
-SYMBOL(ATOMIC_INT_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_LLONG_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_LONG_LOGK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_POINTER_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_SHORT_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_VAR_INIT, None, <stdatomic.h>)
-SYMBOL(ATOMIC_WCHAR_T_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(BUFSIZ, None, <stdio.h>)
-SYMBOL(CHAR_BIT, None, <limits.h>)
-SYMBOL(CHAR_MAX, None, <limits.h>)
-SYMBOL(CHAR_MIN, None, <limits.h>)
-SYMBOL(CLOCKS_PER_SEC, None, <time.h>)
-SYMBOL(CMPLX, None, <complex.h>)
-SYMBOL(CMPLXF, None, <complex.h>)
-SYMBOL(CMPLXL, None, <complex.h>)
-SYMBOL(DBL_DECIMAL_DIG, None, <float.h>)
-SYMBOL(DBL_DIG, None, <float.h>)
-SYMBOL(DBL_EPSILON, None, <float.h>)
-SYMBOL(DBL_HAS_SUBNORM, None, <float.h>)
-SYMBOL(DBL_MANT_DIG, None, <float.h>)
-SYMBOL(DBL_MAX, None, <float.h>)
-SYMBOL(DBL_MAX_10_EXP, None, <float.h>)
-SYMBOL(DBL_MAX_EXP, None, <float.h>)
-SYMBOL(DBL_MIN, None, <float.h>)
-SYMBOL(DBL_MIN_10_EXP, None, <float.h>)
-SYMBOL(DBL_MIN_EXP, None, <float.h>)
-SYMBOL(DBL_TRUE_MIN, None, <float.h>)
-SYMBOL(DECIMAL_DIG, None, <float.h>)
-SYMBOL(EDOM, None, <errno.h>)
-SYMBOL(EILSEQ, None, <errno.h>)
-SYMBOL(EOF, None, <stdio.h>)
-SYMBOL(ERANGE, None, <errno.h>)
-SYMBOL(EXIT_FAILURE, None, <stdlib.h>)
-SYMBOL(EXIT_SUCCESS, None, <stdlib.h>)
-SYMBOL(FE_ALL_EXCEPT, None, <fenv.h>)
-SYMBOL(FE_DFL_ENV, None, <fenv.h>)
-SYMBOL(FE_DIVBYZERO, None, <fenv.h>)
-SYMBOL(FE_DOWNWARD, None, <fenv.h>)
-SYMBOL(FE_INEXACT, None, <fenv.h>)
-SYMBOL(FE_INVALID, None, <fenv.h>)
-SYMBOL(FE_OVERFLOW, None, <fenv.h>)
-SYMBOL(FE_TONEAREST, None, <fenv.h>)
-SYMBOL(FE_TOWARDZERO, None, <fenv.h>)
-SYMBOL(FE_UNDERFLOW, None, <fenv.h>)
-SYMBOL(FE_UPWARD, None, <fenv.h>)
 SYMBOL(FILE, None, <stdio.h>)
-SYMBOL(FILENAME_MAX, None, <stdio.h>)
-SYMBOL(FLT_DECIMAL_DIG, None, <float.h>)
-SYMBOL(FLT_DIG, None, <float.h>)
-SYMBOL(FLT_EPSILON, None, <float.h>)
-SYMBOL(FLT_EVAL_METHOD, None, <float.h>)
-SYMBOL(FLT_HAS_SUBNORM, None, <float.h>)
-SYMBOL(FLT_MANT_DIG, None, <float.h>)
-SYMBOL(FLT_MAX, None, <float.h>)
-SYMBOL(FLT_MAX_10_EXP, None, <float.h>)
-SYMBOL(FLT_MAX_EXP, None, <float.h>)
-SYMBOL(FLT_MIN, None, <float.h>)
-SYMBOL(FLT_MIN_10_EXP, None, <float.h>)
-SYMBOL(FLT_MIN_EXP, None, <float.h>)
-SYMBOL(FLT_RADIX, None, <float.h>)
-SYMBOL(FLT_ROUNDS, None, <float.h>)
-SYMBOL(FLT_TRUE_MIN, None, <float.h>)
-SYMBOL(FOPEN_MAX, None, <stdio.h>)
-SYMBOL(FP_INFINITE, None, <math.h>)
-SYMBOL(FP_NAN, None, <math.h>)
-SYMBOL(FP_NORNAL, None, <math.h>)
-SYMBOL(FP_SUBNORMAL, None, <math.h>)
-SYMBOL(FP_ZERO, None, <math.h>)
-SYMBOL(HUGE_VAL, None, <math.h>)
-SYMBOL(HUGE_VALF, None, <math.h>)
-SYMBOL(HUGE_VALL, None, <math.h>)
-SYMBOL(I, None, <complex.h>)
-SYMBOL(INFINITY, None, <math.h>)
-SYMBOL(INT16_MAX, None, <stdint.h>)
-SYMBOL(INT16_MIN, None, <stdint.h>)
-SYMBOL(INT32_MAX, None, <stdint.h>)
-SYMBOL(INT32_MIN, None, <stdint.h>)
-SYMBOL(INT64_MAX, None, <stdint.h>)
-SYMBOL(INT64_MIN, None, <stdint.h>)
-SYMBOL(INT8_MAX, None, <stdint.h>)
-SYMBOL(INT8_MIN, None, <stdint.h>)
-SYMBOL(INTMAX_MAX, None, <stdint.h>)
-SYMBOL(INTMAX_MIN, None, <stdint.h>)
-SYMBOL(INTPTR_MAX, None, <stdint.h>)
-SYMBOL(INTPTR_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST16_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST16_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST32_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST32_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST64_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST64_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST8_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST8_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST16_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST16_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST32_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST32_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST64_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST64_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST8_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST8_MIN, None, <stdint.h>)
-SYMBOL(INT_MAX, None, <limits.h>)
-SYMBOL(INT_MIN, None, <limits.h>)
-SYMBOL(LC_ALL, None, <locale.h>)
-SYMBOL(LC_COLLATE, None, <locale.h>)
-SYMBOL(LC_CTYPE, None, <locale.h>)
-SYMBOL(LC_MONETARY, None, <locale.h>)
-SYMBOL(LC_NUMERIC, None, <locale.h>)
-SYMBOL(LC_TIME, None, <locale.h>)
-SYMBOL(LDBL_DECIMAL_DIG, None, <float.h>)
-SYMBOL(LDBL_DIG, None, <float.h>)
-SYMBOL(LDBL_EPSILON, None, <float.h>)
-SYMBOL(LDBL_HAS_SUBNORM, None, <float.h>)
-SYMBOL(LDBL_MANT_DIG, None, <float.h>)
-SYMBOL(LDBL_MAX, None, <float.h>)
-SYMBOL(LDBL_MAX_10_EXP, None, <float.h>)
-SYMBOL(LDBL_MAX_EXP, None, <float.h>)
-SYMBOL(LDBL_MIN, None, <float.h>)
-SYMBOL(LDBL_MIN_10_EXP, None, <float.h>)
-SYMBOL(LDBL_MIN_EXP, None, <float.h>)
-SYMBOL(LDBL_TRUE_MIN, None, <float.h>)
-SYMBOL(LLONG_MAX, None, <limits.h>)
-SYMBOL(LLONG_MIN, None, <limits.h>)
-SYMBOL(LONG_MAX, None, <limits.h>)
-SYMBOL(LONG_MIN, None, <limits.h>)
-SYMBOL(L_tmpnam, None, <stdio.h>)
-SYMBOL(L_tmpnam_s, None, <stdio.h>)
-SYMBOL(MATH_ERREXCEPT, None, <math.h>)
-SYMBOL(MATH_ERRNO, None, <math.h>)
-SYMBOL(MB_CUR_MAX, None, <stdlib.h>)
-SYMBOL(MB_LEN_MAX, None, <limits.h>)
-SYMBOL(NAN, None, <math.h>)
-SYMBOL(ONCE_FLAG_INIT, None, <threads.h>)
-SYMBOL(PTRDIFF_MAX, None, <stdint.h>)
-SYMBOL(PTRDIFF_MIN, None, <stdint.h>)
-SYMBOL(RAND_MAX, None, <stdlib.h>)
-SYMBOL(RSIZE_MAX, None, <stdint.h>)
-SYMBOL(SCHAR_MAX, None, <limits.h>)
-SYMBOL(SCHAR_MIN, None, <limits.h>)
-SYMBOL(SEEK_CUR, None, <stdio.h>)
-SYMBOL(SEEK_END, None, <stdio.h>)
-SYMBOL(SEEK_SET, None, <stdio.h>)
-SYMBOL(SHRT_MAX, None, <limits.h>)
-SYMBOL(SHRT_MIN, None, <limits.h>)
-SYMBOL(SIGABRT, None, <signal.h>)
-SYMBOL(SIGFPE, None, <signal.h>)
-SYMBOL(SIGILL, None, <signal.h>)
-SYMBOL(SIGINT, None, <signal.h>)
-SYMBOL(SIGSEGV, None, <signal.h>)
-SYMBOL(SIGTERM, None, <signal.h>)
-SYMBOL(SIG_ATOMIC_MAX, None, <stdint.h>)
-SYMBOL(SIG_ATOMIC_MIN, None, <stdint.h>)
-SYMBOL(SIG_DFL, None, <signal.h>)
-SYMBOL(SIG_ERR, None, <signal.h>)
-SYMBOL(SIG_IGN, None, <signal.h>)
-SYMBOL(SIZE_MAX, None, <stdint.h>)
-SYMBOL(TIME_UTC, None, <time.h>)
-SYMBOL(TMP_MAX, None, <stdio.h>)
-SYMBOL(TMP_MAX_S, None, <stdio.h>)
-SYMBOL(TSS_DTOR_ITERATIONS, None, <threads.h>)
-SYMBOL(UCHAR_MAX, None, <limits.h>)
-SYMBOL(UINT16_MAX, None, <stdint.h>)
-SYMBOL(UINT32_MAX, None, <stdint.h>)
-SYMBOL(UINT64_MAX, None, <stdint.h>)
-SYMBOL(UINT8_MAX, None, <stdint.h>)
-SYMBOL(UINTMAX_MAX, None, <stdint.h>)
-SYMBOL(UINTPTR_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST16_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST32_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST64_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST8_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST16_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST32_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST64_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST8_MAX, None, <stdint.h>)
-SYMBOL(UINT_MAX, None, <limits.h>)
-SYMBOL(ULLONG_MAX, None, <limits.h>)
-SYMBOL(ULONG_MAX, None, <limits.h>)
-SYMBOL(USHRT_MAX, None, <limits.h>)
-SYMBOL(WCHAR_MAX, None, <wchar.h>)
-SYMBOL(WCHAR_MIN, None, <wchar.h>)
-SYMBOL(WEOF, None, <wchar.h>)
-SYMBOL(WINT_MAX, None, <stdint.h>)
-SYMBOL(WINT_MIN, None, <stdint.h>)
-SYMBOL(_Complex_I, None, <complex.h>)
-SYMBOL(_IOFBF, None, <stdio.h>)
-SYMBOL(_IOLBF, None, <stdio.h>)
-SYMBOL(_IONBF, None, <stdio.h>)
-SYMBOL(_Imaginary_I, None, <complex.h>)
-SYMBOL(__alignas_is_defined, None, <stdalign.h>)
-SYMBOL(__alignof_is_defined, None, <stdalign.h>)
-SYMBOL(abort_handler_s, None, <stdlib.h>)
+SYMBOL_VERSION(_Exit, None, <stdlib.h>, c99)
+SYMBOL(abort, None, <stdlib.h>)
+SYMBOL_VERSION(abort_handler_s, None, <stdlib.h>, c11)
 SYMBOL(abs, None, <stdlib.h>)
 SYMBOL(acos, None, <math.h>)
-SYMBOL(acosf, None, <math.h>)
-SYMBOL(acosh, None, <math.h>)
-SYMBOL(acoshf, None, <math.h>)
-SYMBOL(acoshl, None, <math.h>)
-SYMBOL(acosl, None, <math.h>)
-SYMBOL(alignas, None, <stdalign.h>)
-SYMBOL(aligned_alloc, None, <stdlib.h>)
-SYMBOL(alignof, None, <stdalign.h>)
-SYMBOL(and, None, <iso646.h>)
-SYMBOL(and_eq, None, <iso646.h>)
+SYMBOL_VERSION(acosf, None, <math.h>, c99)
+SYMBOL_VERSION(acosh, None, <math.h>, c99)
+SYMBOL_VERSION(acoshf, None, <math.h>, c99)
+SYMBOL_VERSION(acoshl, None, <math.h>, c99)
+SYMBOL_VERSION(acosl, None, <math.h>, c99)
+SYMBOL_VERSION(aligned_alloc, None, <stdlib.h>, c11)
 SYMBOL(asctime, None, <time.h>)
-SYMBOL(asctime_s, None, <time.h>)
+SYMBOL_VERSION(asctime_s, None, <time.h>, c11)
 SYMBOL(asin, None, <math.h>)
-SYMBOL(asinf, None, <math.h>)
-SYMBOL(asinh, None, <math.h>)
-SYMBOL(asinhf, None, <math.h>)
-SYMBOL(asinhl, None, <math.h>)
-SYMBOL(asinl, None, <math.h>)
-SYMBOL(assert, None, <assert.h>)
-SYMBOL(at_quick_exit, None, <stdlib.h>)
+SYMBOL_VERSION(asinf, None, <math.h>, c99)
+SYMBOL_VERSION(asinh, None, <math.h>, c99)
+SYMBOL_VERSION(asinhf, None, <math.h>, c99)
+SYMBOL_VERSION(asinhl, None, <math.h>, c99)
+SYMBOL_VERSION(asinl, None, <math.h>, c99)
+SYMBOL_VERSION(at_quick_exit, None, <stdlib.h>, c11)
 SYMBOL(atan, None, <math.h>)
 SYMBOL(atan2, None, <math.h>)
-SYMBOL(atan2f, None, <math.h>)
-SYMBOL(atan2l, None, <math.h>)
-SYMBOL(atanf, None, <math.h>)
-SYMBOL(atanh, None, <math.h>)
-SYMBOL(atanhf, None, <math.h>)
-SYMBOL(atanhl, None, <math.h>)
-SYMBOL(atanl, None, <math.h>)
+SYMBOL_VERSION(atan2f, None, <math.h>, c99)
+SYMBOL_VERSION(atan2l, None, <math.h>, c99)
+SYMBOL_VERSION(atanf, None, <math.h>, c99)
+SYMBOL_VERSION(atanh, None, <math.h>, c99)
+SYMBOL_VERSION(atanhf, None, <math.h>, c99)
+SYMBOL_VERSION(atanhl, None, <math.h>, c99)
+SYMBOL_VERSION(atanl, None, <math.h>, c99)
 SYMBOL(atexit, None, <stdlib.h>)
 SYMBOL(atof, None, <stdlib.h>)
 SYMBOL(atoi, None, <stdlib.h>)
 SYMBOL(atol, None, <stdlib.h>)
-SYMBOL(atoll, None, <stdlib.h>)
-SYMBOL(atomic_bool, None, <stdatomic.h>)
-SYMBOL(atomic_char, None, <stdatomic.h>)
-SYMBOL(atomic_char16_t, None, <stdatomic.h>)
-SYMBOL(atomic_char32_t, None, <stdatomic.h>)
+SYMBOL_VERSION(atoll,...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Jun 28, 2025

@llvm/pr-subscribers-clang-modules

Author: Vincent (Mr-Anyone)

Changes

Clang now tries to suggest and hint standard library include file by emitting the following.

    4 |     std::unordered_map&lt;std::string, std::string&gt; map;
      |          ^~~~~~~~~~~~~
main.cpp:4:10: note: maybe try to include &lt;unordered_map&gt;; 'std::unordered_map' is defined in &lt;unordered_map&gt;
main.cpp:4:10: note: 'std::unordered_map' is a c++11 feature
main.cpp:4:42: note: maybe try to include &lt;string&gt;; 'std::string' is defined in &lt;string&gt;

This works for both C and C++.

fixes #120388


Patch is 644.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146227.diff

26 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4)
  • (modified) clang/include/clang/Sema/Sema.h (+10)
  • (modified) clang/include/clang/Tooling/Inclusions/StandardLibrary.h (+22)
  • (modified) clang/lib/Parse/ParseExprCXX.cpp (+14)
  • (modified) clang/lib/Sema/CMakeLists.txt (+1)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+49)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+6)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc (+429-697)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp (+55-5)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc (-5)
  • (modified) clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc (+2014-2140)
  • (modified) clang/test/Headers/stddef.c (+40-6)
  • (modified) clang/test/Headers/stddefneeds.c (+67-13)
  • (modified) clang/test/Headers/stddefneeds.cpp (+10-10)
  • (modified) clang/test/Modules/implicit-declared-allocation-functions.cppm (+12-6)
  • (modified) clang/test/Modules/macro-reexport.cpp (+3-3)
  • (modified) clang/test/Modules/stddef.cpp (+2-2)
  • (modified) clang/test/Sema/MicrosoftCompatibility.c (+1-1)
  • (modified) clang/test/Sema/builtin-setjmp.c (+5-3)
  • (modified) clang/test/Sema/c23-delayed-typo-correction-crashes.c (+2-1)
  • (modified) clang/test/Sema/implicit-builtin-decl.c (+2-1)
  • (added) clang/test/Sema/include-suggestion.c (+5)
  • (modified) clang/test/SemaCXX/constructor-initializer.cpp (+1-1)
  • (added) clang/test/SemaCXX/include-suggestions-cxx.cpp (+2458)
  • (modified) clang/test/SemaCXX/no-implicit-builtin-decls.cpp (+1-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 96477ef6ddc9a..b38dafb06e3ca 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -470,6 +470,7 @@ Improvements to Clang's diagnostics
   diagnostics. This fixes a bunch of `bool` being printed as `_Bool`, and also
   a bunch of HLSL types being printed as their C++ equivalents.
 - Clang now consistently quotes expressions in diagnostics.
+- Clang now suggest standard library include path and its associated C++ or C language version.
 - When printing types for diagnostics, clang now doesn't suppress the scopes of
   template arguments contained within nested names.
 - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f2f2152b8bbbe..96f444544291d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5978,6 +5978,10 @@ def err_template_expansion_into_fixed_list : Error<
   "template|concept}0">;
 def note_parameter_type : Note<
   "parameter of type %0 is declared here">;
+def note_standard_lib_include_suggestion : Note<
+  "maybe try to include %0; '%1' is defined in %0">;
+def note_standard_lib_version : Note<
+  "'%0' is a %1 feature">;
 
 // C++11 Variadic Templates
 def err_template_param_pack_default_arg : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9397546c8fc5d..f4c22cc255876 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3611,6 +3611,16 @@ class Sema final : public SemaBase {
                                ParsedType &SuggestedType,
                                bool IsTemplateName = false);
 
+  // Try to suggest the missing standard library include files
+  //
+  // \param SymbolName the symbol name like 'cout'
+  // \param SourceLocation the location of the note being emitted
+  // \param Namespace the namespace that must end with ::, so like 'std::'
+  void NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                            StringRef Namespace);
+  void NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                            const CXXScopeSpec *SS);
+
   /// Attempt to behave like MSVC in situations where lookup of an unqualified
   /// type name has failed in a dependent context. In these situations, we
   /// automatically form a DependentTypeName that will retry lookup in a related
diff --git a/clang/include/clang/Tooling/Inclusions/StandardLibrary.h b/clang/include/clang/Tooling/Inclusions/StandardLibrary.h
index 147f505ade058..42bbb5b3f0d8c 100644
--- a/clang/include/clang/Tooling/Inclusions/StandardLibrary.h
+++ b/clang/include/clang/Tooling/Inclusions/StandardLibrary.h
@@ -29,6 +29,27 @@ class NamespaceDecl;
 class DeclContext;
 namespace tooling {
 namespace stdlib {
+enum Version {
+  Unknown,
+
+  // c++ versions
+  CPlusPlusStart,
+  CPlusPlus11,
+  CPlusPlus14,
+  CPlusPlus17,
+  CPlusPlus20,
+  CPlusPlus23,
+  CPlusPlus26,
+  CPlusPlusEnd,
+
+  // c version
+  CStart,
+  C99,
+  C11,
+  CEnd
+};
+
+llvm::StringRef GetAsString(Version Ver);
 
 class Symbol;
 enum class Lang { C = 0, CXX, LastValue = CXX };
@@ -85,6 +106,7 @@ class Symbol {
   std::optional<Header> header() const;
   // Some symbols may be provided by multiple headers.
   llvm::SmallVector<Header> headers() const;
+  Version version() const;
 
 private:
   Symbol(unsigned ID, Lang Language) : ID(ID), Language(Language) {}
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 1ea0cf52933f6..9de0e9ca74c6f 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -226,6 +226,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
     HasScopeSpecifier = true;
   }
 
+  // If `FailedNestedNameBuilding` is true, attempt to suggest the standard
+  // include file corresponding to the current `FullNamespace` and symbol.
+  std::string FullNamespace = "";
+  bool FailedNesatedNameBuilding = false;
+
   // Preferred type might change when parsing qualifiers, we need the original.
   auto SavedType = PreferredType;
   while (true) {
@@ -454,6 +459,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
       // We have an identifier followed by a '::'. Lookup this name
       // as the name in a nested-name-specifier.
       Token Identifier = Tok;
+      FullNamespace += Identifier.getIdentifierInfo()->getName();
+      FullNamespace += "::";
+
       SourceLocation IdLoc = ConsumeToken();
       assert(Tok.isOneOf(tok::coloncolon, tok::colon) &&
              "NextToken() not working properly!");
@@ -465,6 +473,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
       if (Actions.ActOnCXXNestedNameSpecifier(
               getCurScope(), IdInfo, EnteringContext, SS, CorrectionFlagPtr,
               OnlyNamespace)) {
+        FailedNesatedNameBuilding = true;
         // Identifier is not recognized as a nested name, but we can have
         // mistyped '::' instead of ':'.
         if (CorrectionFlagPtr && IsCorrectedToColon) {
@@ -554,6 +563,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
     break;
   }
 
+  if (FailedNesatedNameBuilding && Tok.getKind() == tok::identifier) {
+    Actions.NoteStandardIncludes(Tok.getIdentifierInfo()->getName(),
+                                 Tok.getLocation(), FullNamespace);
+  }
+
   // Even if we didn't see any pieces of a nested-name-specifier, we
   // still check whether there is a tilde in this position, which
   // indicates a potential pseudo-destructor.
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 51e0ee10b080b..ff4f583bdd9bf 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -115,4 +115,5 @@ add_clang_library(clangSema
   clangEdit
   clangLex
   clangSupport
+  clangToolingInclusionsStdlib
   )
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e1cccf068b5aa..7d659a6d06f93 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -58,10 +58,12 @@
 #include "clang/Sema/SemaSwift.h"
 #include "clang/Sema/SemaWasm.h"
 #include "clang/Sema/Template.h"
+#include "clang/Tooling/Inclusions/StandardLibrary.h"
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/TargetParser/Triple.h"
@@ -805,6 +807,52 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
     assert(SS && SS->isInvalid() &&
            "Invalid scope specifier has already been diagnosed");
   }
+
+  // don't note standard include files for OpenCL and Objective C
+  if ((getLangOpts().CPlusPlus || getLangOpts().C99) && !getLangOpts().OpenCL &&
+      !getLangOpts().ObjC)
+    NoteStandardIncludes(II->getName(), IILoc, SS);
+}
+
+void Sema::NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                                StringRef Namespace) {
+  using clang::tooling::stdlib::Lang;
+
+  llvm::StringRef HeaderName = "";
+  tooling::stdlib::Lang LangOption = tooling::stdlib::Lang::C;
+  if (getLangOpts().CPlusPlus)
+    LangOption = clang::tooling::stdlib::Lang::CXX;
+
+  if (auto StdSym =
+          tooling::stdlib::Symbol::named(Namespace, SymbolName, LangOption)) {
+    if (auto Header = StdSym->header()) {
+      HeaderName = Header->name();
+      Diag(IILoc, diag::note_standard_lib_include_suggestion)
+          << HeaderName << (Namespace + SymbolName).str();
+
+      // Noting the C/C++ version as well
+      if (StdSym->version() != tooling::stdlib::Unknown) {
+        llvm::StringRef CPlusPlusVersion =
+            tooling::stdlib::GetAsString(StdSym->version());
+
+        Diag(IILoc, diag::note_standard_lib_version)
+            << (Namespace + SymbolName).str() << CPlusPlusVersion;
+      }
+    }
+  }
+}
+
+void Sema::NoteStandardIncludes(StringRef SymbolName, SourceLocation IILoc,
+                                const CXXScopeSpec *SS) {
+  std::string Namespace = "";
+  if (SS) {
+    llvm::raw_string_ostream Stream(Namespace);
+    if (SS->isValid())
+      SS->getScopeRep()->dump(Stream);
+    Stream.flush();
+  }
+
+  NoteStandardIncludes(SymbolName, IILoc, Namespace);
 }
 
 /// Determine whether the given result set contains either a type name
@@ -16784,6 +16832,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
   }
 
   Diag(Loc, diag_id) << &II;
+  NoteStandardIncludes(II.getName(), Loc, "");
   if (Corrected) {
     // If the correction is going to suggest an implicitly defined function,
     // skip the correction as not being a particularly good idea.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fc2819458a4ff..9015b70deb5d1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2660,11 +2660,17 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
   if (!SS.isEmpty()) {
     Diag(R.getNameLoc(), diag::err_no_member)
         << Name << computeDeclContext(SS, false) << NameRange;
+    NoteStandardIncludes(Name.getAsString(), R.getNameLoc(), &SS);
     return true;
   }
 
   // Give up, we can't recover.
   Diag(R.getNameLoc(), diagnostic) << Name << NameRange;
+
+  // don't note standard include files for OpenCL and Objective C
+  if ((getLangOpts().CPlusPlus || getLangOpts().C99) && !getLangOpts().OpenCL &&
+      !getLangOpts().ObjC)
+    NoteStandardIncludes(Name.getAsString(), R.getNameLoc(), /*Namespace=*/"");
   return true;
 }
 
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
index 463ce921f0672..b3a1921f3c74b 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
@@ -6,246 +6,44 @@
 // This file was generated automatically by
 // clang/tools/include-mapping/gen_std.py, DO NOT EDIT!
 //
-// Generated from cppreference offline HTML book (modified on 2018-10-28).
+// Generated from cppreference offline HTML book (modified on 2025-02-10).
 //===----------------------------------------------------------------------===//
 
-SYMBOL(ATOMIC_BOOL_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_CHAR16_T_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_CHAR32_T_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_CHAR_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_FLAG_INIT, None, <stdatomic.h>)
-SYMBOL(ATOMIC_INT_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_LLONG_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_LONG_LOGK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_POINTER_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_SHORT_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(ATOMIC_VAR_INIT, None, <stdatomic.h>)
-SYMBOL(ATOMIC_WCHAR_T_LOCK_FREE, None, <stdatomic.h>)
-SYMBOL(BUFSIZ, None, <stdio.h>)
-SYMBOL(CHAR_BIT, None, <limits.h>)
-SYMBOL(CHAR_MAX, None, <limits.h>)
-SYMBOL(CHAR_MIN, None, <limits.h>)
-SYMBOL(CLOCKS_PER_SEC, None, <time.h>)
-SYMBOL(CMPLX, None, <complex.h>)
-SYMBOL(CMPLXF, None, <complex.h>)
-SYMBOL(CMPLXL, None, <complex.h>)
-SYMBOL(DBL_DECIMAL_DIG, None, <float.h>)
-SYMBOL(DBL_DIG, None, <float.h>)
-SYMBOL(DBL_EPSILON, None, <float.h>)
-SYMBOL(DBL_HAS_SUBNORM, None, <float.h>)
-SYMBOL(DBL_MANT_DIG, None, <float.h>)
-SYMBOL(DBL_MAX, None, <float.h>)
-SYMBOL(DBL_MAX_10_EXP, None, <float.h>)
-SYMBOL(DBL_MAX_EXP, None, <float.h>)
-SYMBOL(DBL_MIN, None, <float.h>)
-SYMBOL(DBL_MIN_10_EXP, None, <float.h>)
-SYMBOL(DBL_MIN_EXP, None, <float.h>)
-SYMBOL(DBL_TRUE_MIN, None, <float.h>)
-SYMBOL(DECIMAL_DIG, None, <float.h>)
-SYMBOL(EDOM, None, <errno.h>)
-SYMBOL(EILSEQ, None, <errno.h>)
-SYMBOL(EOF, None, <stdio.h>)
-SYMBOL(ERANGE, None, <errno.h>)
-SYMBOL(EXIT_FAILURE, None, <stdlib.h>)
-SYMBOL(EXIT_SUCCESS, None, <stdlib.h>)
-SYMBOL(FE_ALL_EXCEPT, None, <fenv.h>)
-SYMBOL(FE_DFL_ENV, None, <fenv.h>)
-SYMBOL(FE_DIVBYZERO, None, <fenv.h>)
-SYMBOL(FE_DOWNWARD, None, <fenv.h>)
-SYMBOL(FE_INEXACT, None, <fenv.h>)
-SYMBOL(FE_INVALID, None, <fenv.h>)
-SYMBOL(FE_OVERFLOW, None, <fenv.h>)
-SYMBOL(FE_TONEAREST, None, <fenv.h>)
-SYMBOL(FE_TOWARDZERO, None, <fenv.h>)
-SYMBOL(FE_UNDERFLOW, None, <fenv.h>)
-SYMBOL(FE_UPWARD, None, <fenv.h>)
 SYMBOL(FILE, None, <stdio.h>)
-SYMBOL(FILENAME_MAX, None, <stdio.h>)
-SYMBOL(FLT_DECIMAL_DIG, None, <float.h>)
-SYMBOL(FLT_DIG, None, <float.h>)
-SYMBOL(FLT_EPSILON, None, <float.h>)
-SYMBOL(FLT_EVAL_METHOD, None, <float.h>)
-SYMBOL(FLT_HAS_SUBNORM, None, <float.h>)
-SYMBOL(FLT_MANT_DIG, None, <float.h>)
-SYMBOL(FLT_MAX, None, <float.h>)
-SYMBOL(FLT_MAX_10_EXP, None, <float.h>)
-SYMBOL(FLT_MAX_EXP, None, <float.h>)
-SYMBOL(FLT_MIN, None, <float.h>)
-SYMBOL(FLT_MIN_10_EXP, None, <float.h>)
-SYMBOL(FLT_MIN_EXP, None, <float.h>)
-SYMBOL(FLT_RADIX, None, <float.h>)
-SYMBOL(FLT_ROUNDS, None, <float.h>)
-SYMBOL(FLT_TRUE_MIN, None, <float.h>)
-SYMBOL(FOPEN_MAX, None, <stdio.h>)
-SYMBOL(FP_INFINITE, None, <math.h>)
-SYMBOL(FP_NAN, None, <math.h>)
-SYMBOL(FP_NORNAL, None, <math.h>)
-SYMBOL(FP_SUBNORMAL, None, <math.h>)
-SYMBOL(FP_ZERO, None, <math.h>)
-SYMBOL(HUGE_VAL, None, <math.h>)
-SYMBOL(HUGE_VALF, None, <math.h>)
-SYMBOL(HUGE_VALL, None, <math.h>)
-SYMBOL(I, None, <complex.h>)
-SYMBOL(INFINITY, None, <math.h>)
-SYMBOL(INT16_MAX, None, <stdint.h>)
-SYMBOL(INT16_MIN, None, <stdint.h>)
-SYMBOL(INT32_MAX, None, <stdint.h>)
-SYMBOL(INT32_MIN, None, <stdint.h>)
-SYMBOL(INT64_MAX, None, <stdint.h>)
-SYMBOL(INT64_MIN, None, <stdint.h>)
-SYMBOL(INT8_MAX, None, <stdint.h>)
-SYMBOL(INT8_MIN, None, <stdint.h>)
-SYMBOL(INTMAX_MAX, None, <stdint.h>)
-SYMBOL(INTMAX_MIN, None, <stdint.h>)
-SYMBOL(INTPTR_MAX, None, <stdint.h>)
-SYMBOL(INTPTR_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST16_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST16_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST32_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST32_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST64_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST64_MIN, None, <stdint.h>)
-SYMBOL(INT_FAST8_MAX, None, <stdint.h>)
-SYMBOL(INT_FAST8_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST16_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST16_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST32_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST32_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST64_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST64_MIN, None, <stdint.h>)
-SYMBOL(INT_LEAST8_MAX, None, <stdint.h>)
-SYMBOL(INT_LEAST8_MIN, None, <stdint.h>)
-SYMBOL(INT_MAX, None, <limits.h>)
-SYMBOL(INT_MIN, None, <limits.h>)
-SYMBOL(LC_ALL, None, <locale.h>)
-SYMBOL(LC_COLLATE, None, <locale.h>)
-SYMBOL(LC_CTYPE, None, <locale.h>)
-SYMBOL(LC_MONETARY, None, <locale.h>)
-SYMBOL(LC_NUMERIC, None, <locale.h>)
-SYMBOL(LC_TIME, None, <locale.h>)
-SYMBOL(LDBL_DECIMAL_DIG, None, <float.h>)
-SYMBOL(LDBL_DIG, None, <float.h>)
-SYMBOL(LDBL_EPSILON, None, <float.h>)
-SYMBOL(LDBL_HAS_SUBNORM, None, <float.h>)
-SYMBOL(LDBL_MANT_DIG, None, <float.h>)
-SYMBOL(LDBL_MAX, None, <float.h>)
-SYMBOL(LDBL_MAX_10_EXP, None, <float.h>)
-SYMBOL(LDBL_MAX_EXP, None, <float.h>)
-SYMBOL(LDBL_MIN, None, <float.h>)
-SYMBOL(LDBL_MIN_10_EXP, None, <float.h>)
-SYMBOL(LDBL_MIN_EXP, None, <float.h>)
-SYMBOL(LDBL_TRUE_MIN, None, <float.h>)
-SYMBOL(LLONG_MAX, None, <limits.h>)
-SYMBOL(LLONG_MIN, None, <limits.h>)
-SYMBOL(LONG_MAX, None, <limits.h>)
-SYMBOL(LONG_MIN, None, <limits.h>)
-SYMBOL(L_tmpnam, None, <stdio.h>)
-SYMBOL(L_tmpnam_s, None, <stdio.h>)
-SYMBOL(MATH_ERREXCEPT, None, <math.h>)
-SYMBOL(MATH_ERRNO, None, <math.h>)
-SYMBOL(MB_CUR_MAX, None, <stdlib.h>)
-SYMBOL(MB_LEN_MAX, None, <limits.h>)
-SYMBOL(NAN, None, <math.h>)
-SYMBOL(ONCE_FLAG_INIT, None, <threads.h>)
-SYMBOL(PTRDIFF_MAX, None, <stdint.h>)
-SYMBOL(PTRDIFF_MIN, None, <stdint.h>)
-SYMBOL(RAND_MAX, None, <stdlib.h>)
-SYMBOL(RSIZE_MAX, None, <stdint.h>)
-SYMBOL(SCHAR_MAX, None, <limits.h>)
-SYMBOL(SCHAR_MIN, None, <limits.h>)
-SYMBOL(SEEK_CUR, None, <stdio.h>)
-SYMBOL(SEEK_END, None, <stdio.h>)
-SYMBOL(SEEK_SET, None, <stdio.h>)
-SYMBOL(SHRT_MAX, None, <limits.h>)
-SYMBOL(SHRT_MIN, None, <limits.h>)
-SYMBOL(SIGABRT, None, <signal.h>)
-SYMBOL(SIGFPE, None, <signal.h>)
-SYMBOL(SIGILL, None, <signal.h>)
-SYMBOL(SIGINT, None, <signal.h>)
-SYMBOL(SIGSEGV, None, <signal.h>)
-SYMBOL(SIGTERM, None, <signal.h>)
-SYMBOL(SIG_ATOMIC_MAX, None, <stdint.h>)
-SYMBOL(SIG_ATOMIC_MIN, None, <stdint.h>)
-SYMBOL(SIG_DFL, None, <signal.h>)
-SYMBOL(SIG_ERR, None, <signal.h>)
-SYMBOL(SIG_IGN, None, <signal.h>)
-SYMBOL(SIZE_MAX, None, <stdint.h>)
-SYMBOL(TIME_UTC, None, <time.h>)
-SYMBOL(TMP_MAX, None, <stdio.h>)
-SYMBOL(TMP_MAX_S, None, <stdio.h>)
-SYMBOL(TSS_DTOR_ITERATIONS, None, <threads.h>)
-SYMBOL(UCHAR_MAX, None, <limits.h>)
-SYMBOL(UINT16_MAX, None, <stdint.h>)
-SYMBOL(UINT32_MAX, None, <stdint.h>)
-SYMBOL(UINT64_MAX, None, <stdint.h>)
-SYMBOL(UINT8_MAX, None, <stdint.h>)
-SYMBOL(UINTMAX_MAX, None, <stdint.h>)
-SYMBOL(UINTPTR_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST16_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST32_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST64_MAX, None, <stdint.h>)
-SYMBOL(UINT_FAST8_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST16_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST32_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST64_MAX, None, <stdint.h>)
-SYMBOL(UINT_LEAST8_MAX, None, <stdint.h>)
-SYMBOL(UINT_MAX, None, <limits.h>)
-SYMBOL(ULLONG_MAX, None, <limits.h>)
-SYMBOL(ULONG_MAX, None, <limits.h>)
-SYMBOL(USHRT_MAX, None, <limits.h>)
-SYMBOL(WCHAR_MAX, None, <wchar.h>)
-SYMBOL(WCHAR_MIN, None, <wchar.h>)
-SYMBOL(WEOF, None, <wchar.h>)
-SYMBOL(WINT_MAX, None, <stdint.h>)
-SYMBOL(WINT_MIN, None, <stdint.h>)
-SYMBOL(_Complex_I, None, <complex.h>)
-SYMBOL(_IOFBF, None, <stdio.h>)
-SYMBOL(_IOLBF, None, <stdio.h>)
-SYMBOL(_IONBF, None, <stdio.h>)
-SYMBOL(_Imaginary_I, None, <complex.h>)
-SYMBOL(__alignas_is_defined, None, <stdalign.h>)
-SYMBOL(__alignof_is_defined, None, <stdalign.h>)
-SYMBOL(abort_handler_s, None, <stdlib.h>)
+SYMBOL_VERSION(_Exit, None, <stdlib.h>, c99)
+SYMBOL(abort, None, <stdlib.h>)
+SYMBOL_VERSION(abort_handler_s, None, <stdlib.h>, c11)
 SYMBOL(abs, None, <stdlib.h>)
 SYMBOL(acos, None, <math.h>)
-SYMBOL(acosf, None, <math.h>)
-SYMBOL(acosh, None, <math.h>)
-SYMBOL(acoshf, None, <math.h>)
-SYMBOL(acoshl, None, <math.h>)
-SYMBOL(acosl, None, <math.h>)
-SYMBOL(alignas, None, <stdalign.h>)
-SYMBOL(aligned_alloc, None, <stdlib.h>)
-SYMBOL(alignof, None, <stdalign.h>)
-SYMBOL(and, None, <iso646.h>)
-SYMBOL(and_eq, None, <iso646.h>)
+SYMBOL_VERSION(acosf, None, <math.h>, c99)
+SYMBOL_VERSION(acosh, None, <math.h>, c99)
+SYMBOL_VERSION(acoshf, None, <math.h>, c99)
+SYMBOL_VERSION(acoshl, None, <math.h>, c99)
+SYMBOL_VERSION(acosl, None, <math.h>, c99)
+SYMBOL_VERSION(aligned_alloc, None, <stdlib.h>, c11)
 SYMBOL(asctime, None, <time.h>)
-SYMBOL(asctime_s, None, <time.h>)
+SYMBOL_VERSION(asctime_s, None, <time.h>, c11)
 SYMBOL(asin, None, <math.h>)
-SYMBOL(asinf, None, <math.h>)
-SYMBOL(asinh, None, <math.h>)
-SYMBOL(asinhf, None, <math.h>)
-SYMBOL(asinhl, None, <math.h>)
-SYMBOL(asinl, None, <math.h>)
-SYMBOL(assert, None, <assert.h>)
-SYMBOL(at_quick_exit, None, <stdlib.h>)
+SYMBOL_VERSION(asinf, None, <math.h>, c99)
+SYMBOL_VERSION(asinh, None, <math.h>, c99)
+SYMBOL_VERSION(asinhf, None, <math.h>, c99)
+SYMBOL_VERSION(asinhl, None, <math.h>, c99)
+SYMBOL_VERSION(asinl, None, <math.h>, c99)
+SYMBOL_VERSION(at_quick_exit, None, <stdlib.h>, c11)
 SYMBOL(atan, None, <math.h>)
 SYMBOL(atan2, None, <math.h>)
-SYMBOL(atan2f, None, <math.h>)
-SYMBOL(atan2l, None, <math.h>)
-SYMBOL(atanf, None, <math.h>)
-SYMBOL(atanh, None, <math.h>)
-SYMBOL(atanhf, None, <math.h>)
-SYMBOL(atanhl, None, <math.h>)
-SYMBOL(atanl, None, <math.h>)
+SYMBOL_VERSION(atan2f, None, <math.h>, c99)
+SYMBOL_VERSION(atan2l, None, <math.h>, c99)
+SYMBOL_VERSION(atanf, None, <math.h>, c99)
+SYMBOL_VERSION(atanh, None, <math.h>, c99)
+SYMBOL_VERSION(atanhf, None, <math.h>, c99)
+SYMBOL_VERSION(atanhl, None, <math.h>, c99)
+SYMBOL_VERSION(atanl, None, <math.h>, c99)
 SYMBOL(atexit, None, <stdlib.h>)
 SYMBOL(atof, None, <stdlib.h>)
 SYMBOL(atoi, None, <stdlib.h>)
 SYMBOL(atol, None, <stdlib.h>)
-SYMBOL(atoll, None, <stdlib.h>)
-SYMBOL(atomic_bool, None, <stdatomic.h>)
-SYMBOL(atomic_char, None, <stdatomic.h>)
-SYMBOL(atomic_char16_t, None, <stdatomic.h>)
-SYMBOL(atomic_char32_t, None, <stdatomic.h>)
+SYMBOL_VERSION(atoll,...
[truncated]

@Mr-Anyone Mr-Anyone marked this pull request as draft June 28, 2025 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggest include file for popular standard functions
2 participants